The following issue has been SUBMITTED. 
====================================================================== 
http://austingroupbugs.net/view.php?id=1164 
====================================================================== 
Reported By:                mikecrowe
Assigned To:                
====================================================================== 
Project:                    1003.1(2016)/Issue7+TC2
Issue ID:                   1164
Category:                   System Interfaces
Type:                       Enhancement Request
Severity:                   Comment
Priority:                   normal
Status:                     New
Name:                       Mike Crowe 
Organization:                
User Reference:              
Section:                    pthread_cond_timedwait 
Page Number:                0 
Line Number:                0 
Interp Status:              --- 
Final Accepted Text:         
====================================================================== 
Date Submitted:             2017-09-30 15:48 UTC
Last Modified:              2017-09-30 15:48 UTC
====================================================================== 
Summary:                    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.
====================================================================== 

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               
======================================================================


Reply via email to