Skip to content

std::condition_variable and std::condition_variable_any #148328

@johnsheu

Description

@johnsheu

wait_for() and wait_until() for std::condition_variable and std::condition_variable_any take their wait duration or timeout parameters by const-reference. This can lead to unexpected behavior if the referent changes while the wait_for() or wait_until() blocks.

For example:

  template <class _Clock, class _Duration>
  _LIBCPP_HIDE_FROM_ABI cv_status
  wait_until(unique_lock<mutex>& __lk, const chrono::time_point<_Clock, _Duration>& __t) {
    using namespace chrono;
    using __clock_tp_ns = time_point<_Clock, nanoseconds>;

    typename _Clock::time_point __now = _Clock::now();
    if (__t <= __now)
      return cv_status::timeout;

    __clock_tp_ns __t_ns = __clock_tp_ns(std::__safe_nanosecond_cast(__t.time_since_epoch()));

    __do_timed_wait(__lk, __t_ns);
    return _Clock::now() < __t ? cv_status::no_timeout : cv_status::timeout;
  }

The duration parameter __t is accessed by-reference, and so its value may be different before and after the wait.

For std::condition_variable_any, this is an actual data race if the timeout parameter is protected by the lock, as the implementation accesses the timeout outside of the lock.

Metadata

Metadata

Assignees

No one assigned

    Labels

    libc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions