https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121141

            Bug ID: 121141
           Summary: [libstdc++] std::shared_timed_mutex::try_lock_until
                    causes assertion failure with negative timepoint
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: dhruvc at nvidia dot com
  Target Milestone: ---

The following code tries to have a call to try_lock_until () always fail
because a negative timepoint has always been passed (per
thread.timedmutex.requirements#general-11):

====

#include <chrono>
#include <shared_mutex>
#include <thread>

using SC = std::chrono::steady_clock;
using DU = std::chrono::duration<float, std::ratio<1, 5>>;

const std::chrono::time_point<SC, DU> tp{DU{-0.1f}};
std::shared_timed_mutex mut;

void thing() {
    (void)mut.try_lock_until(tp); 
}

int main() {
    mut.lock();
    std::thread t(thing);
    t.join();
}

====

Compilation options: -std=c++14

However this leads to a runtime error:

/opt/compiler-explorer/gcc-trunk-20250716/include/c++/16.0.0/shared_mutex:565:
bool std::shared_timed_mutex::try_lock_until(const
std::chrono::time_point<std::chrono::_V2::steady_clock, _Duration>&) [with
_Duration = std::chrono::duration<float, std::ratio<1, 5> >]: Assertion '__ret
== 0' failed.
Program terminated with signal: SIGSEGV

Compiler explorer link: https://godbolt.org/z/j7nbTcoz5

This is because the code in the standard library does not check the return
value from pthread_rwlock_clockwrlock when the timepoint is negative:

        int __ret = pthread_rwlock_clockwrlock(&_M_rwlock, CLOCK_MONOTONIC,
                                               &__ts);
        // On self-deadlock, we just fail to acquire the lock.  Technically,
        // the program violated the precondition.
        if (__ret == ETIMEDOUT || __ret == EDEADLK)
          return false;
        // Errors not handled: EINVAL
        __glibcxx_assert(__ret == 0);
        return true;

Reply via email to