Re: std::shared_mutex deadlock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 6 Mar 2023, 08:23 Bastian Hauda via Gcc-help, <gcc-help@xxxxxxxxxxx>
wrote:

> Hi,
> I observe a deadlock from time to time using the msvc + microsoft std
> library and recently asked a question about std::shared_mutex in their dev
> forum:
>
> https://developercommunity.visualstudio.com/t/std::shared_mutex-deadlock/10299619#T-ND10299805
>
> Now I would like to know if the gnu std library exhibits the same
> behaviour.
> (I just could not test the code on Linux yet.)
>

You could use Compiler Explorer: https://gcc.godbolt.org/


>
> In short:
> Thread C tries(!) to write access (lock via scoped_lock or unique_lock)
> while Thread B already has(!) it shared locked - read access (via
> std::shared_lock).
> Meanwhile Thread A is also trying(!) to read access (via std::shared_lock)
> the shared_mutex.
>
> In order:
> Thread B: std::shared_lock _(mutex); // ok - acquired and now waiting for
> Thread A to finish
> Thread C: std::scoped_lock _(mutex); // ok - stuck for now
> Thread A: std::shared_lock _(mutex); // failure - stuck as well
>
> -> Thread C should be stuck but Thread A should be able to acquire the
> shared lock and continue but it is stuck as well.
>

No, that's not guaranteed by the C++ standard. If you assume that behaviour
is guaranteed, then your program has a bug.

The behaviour you expect can lead to writer starvation, where thread C is
never able to acquire the lock, because there is always at least one
reader. The way to avoid writer starvation is to have a flag saying there
is at least one thread waiting for an exclusive lock, and to block later
attempts to take a shared lock. That way the writer can make progress.

The problem here is that you've made thread A depend on thread B, and wait
for it while holding a lock. That's a bad idea.

Libstdc++ has two shared_mutex implementations. The first one is used if
the OS supports POSIX pthread_rwlock_t, and then it's up to the OS's
Pthreads implementation whether readers or writers get priority. The second
implementation has the following comment, making it very clear that your
expectation is wrong:

    // This means that when no reader locks are held readers and writers get
    // equal priority. When one or more reader locks is held a writer gets
    // priority and no more reader locks can be taken while the writer is
    // queued.

This logic is based on the reference implementation of std::shared_mutex
described in the original proposal to add it to the C++ standard:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2406.html#shared_mutex_imp



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux