Async-std: StdoutLock not released on drop.

Created on 21 Dec 2019  路  10Comments  路  Source: async-rs/async-std

This causes a deadlock with 1.4.0 :

async fn f() {
    {
        let _ = async_std::io::stdout().lock().await;
    }
    {
        let _ = async_std::io::stdout().lock().await;
    }
}
bug

Most helpful comment

Typically a mutex can be unlocked only by the owner, i.e., thread that locked it. The std::io::StdoutLock is no different since on POSIX systems it uses pthread mutex with such a requirement. It is also marked as !Send to enforce that.

All 10 comments

I'm noticing something similar with some mutexes at the moment. I'll see if I can post some sample code tomorrow to reproduce my issue. It looks like mutexes don't relinquish locks, even when I make the calls to drop() explicitly.

async_std::io::StdoutLock is a thin wrapper around similar struct from std
with an additional unasfe impl of Send trait. The mutex used internally in
std::io::StdoutLock can be unlocked only from the same thread.

Thus in scenario above unlocking will fail (silently or with panic, depending
on debug assertions in std), hence a deadlock.

@tmiasko Does anything similar apply to Mutex, or does this just affect StdoutLock?

The mutex used internally in std::io::StdoutLock can be unlocked only from the same thread.

@tmiasko could you perhaps share more on this?

Typically a mutex can be unlocked only by the owner, i.e., thread that locked it. The std::io::StdoutLock is no different since on POSIX systems it uses pthread mutex with such a requirement. It is also marked as !Send to enforce that.

Interesting. This could be pretty confusing and counter-intuitive behavior for many people. Are there any plans to address this sort of behavior within async-std? I'm assuming fixing this would require changes to the task scheduler, at the very least.

@Noah-Kennedy from talking with @stjepang in a call yesterday, we're considering maybe dropping this range of APIs all together. The new scheduler outlined in https://github.com/async-rs/async-std/pull/631 would help with any (potentially) slow IO.

There are probably ways of writing true async stdio APIs, but to make them coordinate with std seemingly requires a lot of effort, and probably buy-in from std itself too. #631 might just be the best option we have for the foreseeable future.

@yoshuawuyts which APIs would be dropped? stdout() and Mutex?

I could see the new scheduler allowing those to be removed, with people just using the Mutex and blocking IO in std, especially where said IO involves a lock.

@Noah-Kennedy just stdout/stdin/stderr; our async mutex impl actually has distinct benefits compared to always blocking threads.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Darksonn picture Darksonn  路  7Comments

yoshuawuyts picture yoshuawuyts  路  6Comments

yoshuawuyts picture yoshuawuyts  路  8Comments

yoshuawuyts picture yoshuawuyts  路  6Comments

Nokel81 picture Nokel81  路  3Comments