Austin Group Defect Tracker

Aardvark Mark III


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0001164 [1003.1(2016)/Issue7+TC2] System Interfaces Comment Enhancement Request 2017-09-30 15:48 2017-09-30 15:48
Reporter mikecrowe View Status public  
Assigned To
Priority normal Resolution Open  
Status New  
Name Mike Crowe
Organization
User Reference
Section pthread_cond_timedwait
Page Number 0
Line Number 0
Interp Status ---
Final Accepted Text
Summary 0001164: Correct C++11 std::condition_variable requires a version of pthread_cond_timedwait that supports specifying the clock
Description C++11's std::condition_variable specifies the clock to be waited upon at
the time of the wait explicitly via the wait_until or implicitly via the
wait_for method. There is no standard way to specify the clock during
construction.

pthread_cond_timedwait uses the clock (optionally) specified via
the pthread_cond_attr_t parameter to pthread_cond_init.

This means that current implementations in libstdc++ and libc++ of
std::condition_variable::wait_for and std::condition_variable::wait_until
create their underlying pthread_cond_t to use CLOCK_REALTIME, and then
convert other clocks to CLOCK_REALTIME before calling
pthread_cond_timedwait. Such waits are prone to racing against the system
clock being set asynchronously, potentially resulting in a much shorter or
longer wait.

I believe that this issue was raised during the standardisation of C++11 as
"DR887"[1]. It appears that at that time those involved believed that it
was possible to implement the feature on top of POSIX threads. In
particular, it is possible to avoid a much-shorter wait by rechecking the
timeout after pthread_cond_timedwait returns. But, it is my understanding,
that there was no solution provided for the wait potentially being much
longer if the system clock is reset back to the past.

A great many C libraries have moved from using CLOCK_REALTIME (usually via
time(2) or gettimeofday(2)) to CLOCK_MONOTONIC (via clock_gettime(2)) in
order to ensure that timeouts do not unexpectedly change when the system
clock changes. They can do so, even when using condition variables, by
specifying CLOCK_MONOTONIC when creating them.

Unfortunately, C++ libraries that try to do the right thing by using
std::chrono::steady_clock absolute timeouts or relative timeouts, are
inadvertently using timeouts based on CLOCK_REALTIME. They cannot portably
do the right thing without resorting to using pthread calls directly.

As a developer of embedded-Linux-based systems that may have their systems
clocks changed, using CLOCK_MONOTONIC rather than CLOCK_REALTIME for
condition variable timeouts is important to me. We have our own condition
variable implementation that uses pthread_condattr_setclock to always use
CLOCK_MONOTONIC and then converts other clocks to that clock. This solution
works, but we'd much rather be using the standard std::condition_variable
implementation. It also means that any third-party C++ libraries we use
must be modified to use our implementation.

I have submitted patches to libstdc++ and glibc to support a new
pthread_cond_timedwaitonclock_np function[2] which accepts a clockid_t to
indicate which clock should be used for the wait. It supports either
CLOCK_REALTIME or CLOCK_MONOTONIC. These patches were received somewhat
warmly, but it was suggested that I raise the issue here.

I see three alternative ways to correctly support std::condition_variable
waits on std::chrono::steady_clock:

1. The addition of a function like pthread_cond_timedwaitonclock_np as
   described above. (Though of course, if approved here it would not be
   _np.)

2. Making std::condition_variable create the underlying pthread_cond_t to
   use CLOCK_MONOTONIC. As described above, this means that code genuinely
   wanting to wait on CLOCK_REALTIME cannot do so. (I could believe that
   there is more code that cares about their waits being immune to system
   clock changes than cares about waits honouring system clock changes
   immediately though.)

3. Implement std::condition_variable on top of non-standard underlying
   operating system factilities such as futex(2). This is the route that
   std::future has taken in libstdc++, but it still falls back to using
   std::condition_variable if futex is not available.

I believe that a similar issue affects std::timed_mutex, but there is
currently no standard way to tell pthread_mutex_timedlock to use a
different clock so method 2 above does not apply. The addition of a
pthread_mutex_timedlockonclock-like function would help there too.


[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41861 [^]
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4486.html [^]
    http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2999.html [^]

[2] https://sourceware.org/ml/libc-alpha/2015-07/msg00193.html [^]
    https://sourceware.org/ml/libc-alpha/2015-08/msg00186.html [^]
    https://sourceware.org/ml/libc-alpha/2015-08/msg00230.html [^]
    https://gcc.gnu.org/ml/libstdc++/2015-07/msg00015.html [^]
Desired Action The addition of pthread_cond_timedwait and pthread_mutex_timedlock variants that accepts clock parameters.
Tags No tags attached.
Attached Files

- Relationships

There are no notes attached to this issue.

- Issue History
Date Modified Username Field Change
2017-09-30 15:48 mikecrowe New Issue
2017-09-30 15:48 mikecrowe Name => Mike Crowe
2017-09-30 15:48 mikecrowe Section => pthread_cond_timedwait
2017-09-30 15:48 mikecrowe Page Number => 0
2017-09-30 15:48 mikecrowe Line Number => 0


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker