Boost C++ Libraries: Ticket #11377: Boost condition variable always waits for system clock deadline https://svn.boost.org/trac10/ticket/11377 <p> On Linux systems using pthreads, the Boost condition variable wait operations are always converted to use the system clock as a time base. This causes problems when the system clock is changed. When the system clock is set back during the wait, the wait operation does not return until the system clock has returned to the absolute time calculated when the wait operation was scheduled. </p> <p> The attached test code and test harness demonstrates this behavior. On my Ubuntu Linux 14.04 system, the test code (when run with the 'until' or 'for' wait operations) hangs after the harness sets the system clock. </p> <p> (see attached test case: build clock_changes and run clock_changes_test.sh) </p> <p> g++ -g -Wall -o clock_changes clock_changes.cpp -I/tools/boost_1_56_0 -L/tools/boost_1_56_0/stage/lib -lboost_thread -lboost_chrono -lboost_program_options -lboost_system -lpthread </p> <p> In our application (and I suppose in a variety of use cases), the application wants to wait for a time relative to a monotonic clock regardless of the behavior of the system clock. </p> <p> The boost sleep operations demonstrate the correct behavior in the face of system clock changes. </p> <p> The Pthread API supports using a monotonic clock for timed waits by setting the clock when the condition variable is initialized. And Issue 7665 seems to imply that condition_variable will be changed to use a monotonic clock: <a class="ext-link" href="https://svn.boost.org/trac/boost/ticket/7665#comment:16"><span class="icon">​</span>https://svn.boost.org/trac/boost/ticket/7665#comment:16</a> </p> <p> In case it's useful, I have attached a modification to boost::condition_variable to create a new class boost::condition_variable_steady that behaves consistently in the face of system clock changes. </p> <p> (see condition_variable_steady.hpp) </p> <p> I'm not sure what the right behavior should be in boost, but I would suggest at least providing a class that operates independently of the system clock. </p> <p> Note: I'm currently using boost 1.56.0, but the condition_variable.hpp header is effectively the same in 1.57.0 and 1.58.0, so I'm almost certain the same issue exists in the most recent release (1.58.0). </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/11377 Trac 1.4.3 Dave Bacher <dbacher@…> Fri, 05 Jun 2015 21:31:37 GMT attachment set https://svn.boost.org/trac10/ticket/11377 https://svn.boost.org/trac10/ticket/11377 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">clock_changes.cpp</span> </li> </ul> <p> Test code to wait in various ways using boost threads/condition variables </p> Ticket Dave Bacher <dbacher@…> Fri, 05 Jun 2015 21:34:19 GMT attachment set https://svn.boost.org/trac10/ticket/11377 https://svn.boost.org/trac10/ticket/11377 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">clock_changes_test.sh</span> </li> </ul> <p> Test harness to run clock_changes and set the system clock </p> Ticket Dave Bacher <dbacher@…> Fri, 05 Jun 2015 21:37:36 GMT attachment set https://svn.boost.org/trac10/ticket/11377 https://svn.boost.org/trac10/ticket/11377 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">condition_variable_steady.hpp</span> </li> </ul> <p> condition_variable header rewritten to use steady clock instead of system clock </p> Ticket viboes Sun, 07 Jun 2015 08:54:16 GMT component changed https://svn.boost.org/trac10/ticket/11377#comment:1 https://svn.boost.org/trac10/ticket/11377#comment:1 <ul> <li><strong>component</strong> <span class="trac-field-old">threads</span> → <span class="trac-field-new">thread</span> </li> </ul> <p> Please, don't use the threads component but the thread one. </p> Ticket viboes Sun, 28 Jun 2015 08:56:45 GMT owner, status changed https://svn.boost.org/trac10/ticket/11377#comment:2 https://svn.boost.org/trac10/ticket/11377#comment:2 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Anthony Williams</span> to <span class="trac-author">viboes</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket viboes Thu, 03 Sep 2015 07:19:59 GMT <link>https://svn.boost.org/trac10/ticket/11377#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:3</guid> <description> <p> Hi, </p> <p> there is already a family of no_interruption_point sleeps that don't use condition variables </p> <pre class="wiki">boost::this_thread::no_interruption_point::sleep_for boost::this_thread::no_interruption_point::sleep_until </pre><p> Does this fix you issue? </p> <p> Could you resume what is the difference between your condition_variable_steady and the condition_variable? </p> </description> <category>Ticket</category> </item> <item> <author>David Bacher <dbacher@…></author> <pubDate>Thu, 03 Sep 2015 15:46:41 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11377#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:4</guid> <description> <p> Thanks for your attention. </p> <blockquote class="citation"> <p> Does this fix you issue? </p> </blockquote> <p> Unfortunately, no. The issue is not with sleep operations, but with semaphore wait operations. When we wait on a semaphore and the system time changes, the wait does not return until the absolute time of the system clock reaches the deadline. Thus, if the system clock is set backwards while the process waits on a semaphore, the process may end up waiting longer than it should -- a 5 second wait may turn into a 1 minute wait if the system clock is set backwards by one minute. In our use case, we don't care about the absolute system time, we just want to time out after a specific duration. </p> <blockquote class="citation"> <p> Could you resume what is the difference between your condition_variable_steady and the condition_variable? </p> </blockquote> <p> There is a minor change in condition_variable_steady to use the monotonic clock when initializing the semaphore and performing wait operations. This fixes the problem described above because the monotonic clock is not affected by changes in the system time. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Thu, 03 Sep 2015 21:00:24 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11377#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:5</guid> <description> <p> Ok, I have adapted a patch from your condition_variable_steady that uses pthread_condattr_setclock. I have no platform providing it (I'm using MacOS). The user will need to define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC until I find a way to detect it. </p> <p> I will commit it soon on develop branch. Could you test it? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Thu, 03 Sep 2015 21:46:12 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/11377#comment:6 https://svn.boost.org/trac10/ticket/11377#comment:6 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.60.0</span> </li> </ul> <p> Add to develop branch <a class="ext-link" href="https://github.com/boostorg/thread/commit/9f883f6ad7377b88b79fa70cc5de68cbfb0213e4"><span class="icon">​</span>https://github.com/boostorg/thread/commit/9f883f6ad7377b88b79fa70cc5de68cbfb0213e4</a> </p> Ticket viboes Sat, 05 Sep 2015 14:22:58 GMT status, milestone changed https://svn.boost.org/trac10/ticket/11377#comment:7 https://svn.boost.org/trac10/ticket/11377#comment:7 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">new</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">Boost 1.60.0</span> → <span class="trac-field-new">To Be Determined</span> </li> </ul> Ticket viboes Tue, 08 Sep 2015 19:43:34 GMT status changed https://svn.boost.org/trac10/ticket/11377#comment:8 https://svn.boost.org/trac10/ticket/11377#comment:8 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket Dave Bacher <dbacher@…> Tue, 08 Sep 2015 21:31:18 GMT <link>https://svn.boost.org/trac10/ticket/11377#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:9</guid> <description> <p> Thanks for addressing this. I will try to help test. </p> <p> As of 9/8, I'm unable to build the thread library from the master or develop branches: </p> <pre class="wiki">$ ./b2 --with-thread ... gcc.compile.c++ bin.v2/libs/thread/build/gcc-4.8/release/threading-multi/pthread/thread.o In file included from ./boost/utility/result_of.hpp:202:0, from ./boost/thread/detail/invoker.hpp:28, from ./boost/thread/future.hpp:20, from libs/thread/src/pthread/thread.cpp:19: ./boost/preprocessor/iteration/detail/iter/forward1.hpp:47:37: fatal error: boost/utility/detail/result_of_iterate.hpp: No such file or directory # include BOOST_PP_FILENAME_1 ^ compilation terminated. "g++" -ftemplate-depth-128 -O3 -finline-functions -Wno-inline -Wall -pedantic -pthread -fPIC -m64 -Wextra -Wno-long-long -Wno-unused-parameter -Wno-variadic-macros -Wunused-function -pedantic -DBOOST_ALL_NO_LIB=1 -DBOOST_ATOMIC_DYN_LINK=1 -DBOOST_SYSTEM_DYN_LINK=1 -DBOOST_THREAD_BUILD_DLL=1 -DBOOST_THREAD_DONT_USE_CHRONO -DBOOST_THREAD_POSIX -DNDEBUG -I"." -c -o "bin.v2/libs/thread/build/gcc-4.8/release/threading-multi/pthread/thread.o" "libs/thread/src/pthread/thread.cpp" </pre><p> I'm new to building boost from the git sources, so it's possible I'm doing something wrong. The chrono and system libraries build fine in my clone. </p> </description> <category>Ticket</category> </item> <item> <author>Dave Bacher <dbacher@…></author> <pubDate>Tue, 08 Sep 2015 21:35:29 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11377#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:10</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/11377#comment:9" title="Comment 9">Dave Bacher &lt;dbacher@…&gt;</a>: </p> <blockquote class="citation"> <p> As of 9/8, I'm unable to build the thread library from the master or develop branches: </p> </blockquote> <p> Sorry, I checked the Boost.Thread Jenkins build and found I was missing the "headers" build step. </p> </description> <category>Ticket</category> </item> <item> <author>Dave Bacher <dbacher@…></author> <pubDate>Tue, 08 Sep 2015 23:06:18 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11377#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:11</guid> <description> <p> The patch is working properly for me. </p> <p> With #define BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC, the test code waits for the specified duration even with the adjustment of the system clock. In the output below, the test completes after 5 seconds even though the system clock was adjusted backwards. Previously, the test would hang until the system clock reached the time the test was started plus 5 seconds. </p> <pre class="wiki">$ sh clock_changes_test.sh [sudo] password: Setup sudo authentication Starting test to wait for 5 seconds Adjusting time to 01:00:00 Waiting for 5 sec WAIT_UNTIL Tue Sep 8 01:00:00 PDT 2015 Waiting... Steady duration/start/stop: 5 3104032404935 nanoseconds since boot / 3109032558479 nanoseconds since boot System duration/start/stop: -52747 seconds 1441751952904865440 nanoseconds since Jan 1, 1970 / 1441699204998073008 nanoseconds since Jan 1, 1970 Test complete, please check your system clock Tue Sep 8 01:00:05 PDT 2015 </pre><p> Regarding when to use the monotonic clock, I think there are separate two issues: </p> <ol><li>Policy -- when should the monotonic clock be used? I would prefer that using the monotonic clock is the default. But perhaps other applications have other expectations. </li></ol><ol start="2"><li>Availability -- how to determine if the monotonic clock is available? On my Linux system, linux/time.h #defines CLOCK_MONOTONIC. At runtime, <a class="ext-link" href="http://linux.die.net/man/3/clock_gettime"><span class="icon">​</span>clock_gettime</a> returns an error if the specified clock id is not available. </li></ol> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Thu, 17 Sep 2015 18:01:35 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11377#comment:12 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:12</guid> <description> <p> Thanks for checking the patch, and glad to see it works for you. </p> <p> As soon as I'm able to detect if the following works as expected I will swithc the implementation on platforms supporting it. </p> <pre class="wiki"> pthread_condattr_setclock(&amp;attr, CLOCK_MONOTONIC); </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Wed, 23 Sep 2015 23:01:58 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/11377#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:13</guid> <description> <p> Please could you try to replace in thread/v2/thread.hpp line <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/94" title="#94: Tasks: Better reporting of failed expectation. (closed: wontfix)">#94</a> </p> <p> #ifdef BOOST_THREAD_SLEEP_FOR_IS_STEADY </p> <p> by </p> <p> #if defined BOOST_THREAD_SLEEP_FOR_IS_STEADY &amp;&amp; ! defined BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Fri, 25 Sep 2015 05:40:54 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/11377#comment:14 https://svn.boost.org/trac10/ticket/11377#comment:14 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.60.0</span> </li> </ul> <p> Please, could you try the develop branch </p> <p> <a class="ext-link" href="https://github.com/boostorg/thread/commit/8f5de1d7c34ff7248261874f273498a622bf76d4"><span class="icon">​</span>https://github.com/boostorg/thread/commit/8f5de1d7c34ff7248261874f273498a622bf76d4</a> </p> Ticket Dave Bacher <dbacher@…> Fri, 25 Sep 2015 22:17:43 GMT <link>https://svn.boost.org/trac10/ticket/11377#comment:15 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/11377#comment:15</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/11377#comment:14" title="Comment 14">viboes</a>: </p> <blockquote class="citation"> <p> Please, could you try the develop branch </p> <p> <a class="ext-link" href="https://github.com/boostorg/thread/commit/8f5de1d7c34ff7248261874f273498a622bf76d4"><span class="icon">​</span>https://github.com/boostorg/thread/commit/8f5de1d7c34ff7248261874f273498a622bf76d4</a> </p> </blockquote> <p> The latest develop branch works for my test case. My test code explicitly #defines BOOST_THREAD_HAS_CONDATTR_SET_CLOCK_MONOTONIC. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sun, 27 Sep 2015 13:42:14 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/11377#comment:16 https://svn.boost.org/trac10/ticket/11377#comment:16 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <blockquote> <p> <a class="ext-link" href="https://github.com/boostorg/thread/commit/730cb550e6d969520c3f39e0ddf5d80351bddf3a"><span class="icon">​</span>https://github.com/boostorg/thread/commit/730cb550e6d969520c3f39e0ddf5d80351bddf3a</a> </p> </blockquote> Ticket