On Tue, 28 Oct 2025 at 08:34, Jonathan Wakely <[email protected]> wrote:
>
>
>
> On Tue, 28 Oct 2025, 08:28 Tomasz Kaminski, <[email protected]> wrote:
>>
>>
>>
>> On Mon, Oct 27, 2025 at 10:29 PM Jonathan Wakely <[email protected]> wrote:
>>>
>>> The test_shared_relative function deadlocks on older Glibc versions that
>>> don't have pthread_rwlock_clockrdlock, because (as already mentioned
>>> earlier in the test file) pthread_rwlock_timedrdlock returns EDEADLK if
>>> the thread that already holds a write lock attempts to acquire read
>>> lock, causing std::shared_timed_mutex to loop forever.
>>>
>>> The fix is to do the invalid try_lock_shared_for call on a different
>>> thread.
>>>
>>> Also add missing -pthread for PR122401.
>>>
>>> libstdc++-v3/ChangeLog:
>>>
>>> PR libstdc++/122401
>>> * testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc:
>>> Do not call try_lock_shared_for from the thread that already
>>> holds the exclusive lock. Add -pthread for et pthread.
>>> ---
>>>
>>> Tested x86_64-linux (Glibc 2.41) and aarch64-linux (Glibc 2.28).
>>
>> LGTM. This is problem in test, as
>> https://eel.is/c++draft/thread.sharedmutex.class#3.2,
>> says that attempting to lock already locked, which try_lock is doing, is UB.
>
>
> Yes, it happens to work with our implementation when using a recent glibc
> release with pthread_rwlock_clockrdlock, but we shouldn't rely on that.
Strictly speaking, we should also use a separate thread for the calls
that try to obtain the exclusive lock when the current thread already
holds the lock:
VERIFY(stm.try_lock_for(d));
VERIFY(!stm.try_lock_for(d));
This is undefined for the same reason, it just happens to work with
our impl (but maybe not on all POSIX systems?)
I'll fix those too, v2 patch coming up.
>
>
>>>
>>> .../shared_timed_mutex/try_lock_until/116586.cc | 12 +++++++++++-
>>> 1 file changed, 11 insertions(+), 1 deletion(-)
>>>
>>> diff --git
>>> a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
>>>
>>> b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
>>> index cebbb3a258d9..aae85487a692 100644
>>> ---
>>> a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
>>> +++
>>> b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
>>> @@ -1,4 +1,7 @@
>>> // { dg-do run { target c++14 } }
>>> +// { dg-additional-options "-pthread" { target pthread } }
>>> +// { dg-require-gthreads "" }
>>> +// { dg-require-effective-target hosted }
>>>
>>> #include <shared_mutex>
>>> #include <chrono>
>>> @@ -66,7 +69,14 @@ test_shared_relative(chrono::nanoseconds offset)
>>> stm.unlock_shared();
>>> // Should complete immediately
>>> VERIFY(stm.try_lock_for(chrono::seconds{10}));
>>> - VERIFY(!stm.try_lock_shared_for(d));
>>> + {
>>> + // NPTL will give us EDEADLK if pthread_rwlock_timedrdlock() is called
>>> on
>>> + // the same thread that already holds the exclusive (write) lock, so
>>> let's
>>> + // arrange for a different thread to try to acquire the shared lock.
>>> + auto t = std::async(std::launch::async, [&stm, d]() {
>>> + VERIFY(!stm.try_lock_shared_for(d));
>>> + });
>>> + }
>>> }
>>>
>>> int main()
>>> --
>>> 2.51.0
>>>