Boost C++ Libraries: Ticket #9708: boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite https://svn.boost.org/trac10/ticket/9708 <p> After upgdate from boost 1.44 to boost 1.52 following issue appears: boost::condition_variable::timed_wait(..., boost::posix_time::time_duration(boost::posix_time::pos_infin)) always immediately return false. In boost 1.44 it waits infinite for a condition notified. </p> <p> Simple test: </p> <div class="wiki-code"><div class="code"><pre><span class="kt">int</span> <span class="nf">_tmain</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">_TCHAR</span><span class="o">*</span> <span class="n">argv</span><span class="p">[])</span> <span class="p">{</span> <span class="c1">// test std</span> <span class="n">std</span><span class="o">::</span><span class="n">condition_variable</span> <span class="n">scv</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="n">mutex</span> <span class="n">sm</span><span class="p">;</span> <span class="kt">bool</span> <span class="n">flag</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="kr">thread</span> <span class="n">t</span><span class="p">([</span><span class="o">&amp;</span><span class="p">]()</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_lock</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">l</span><span class="p">(</span><span class="n">sm</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">cv_status</span><span class="o">::</span><span class="n">timeout</span> <span class="o">==</span> <span class="n">scv</span><span class="p">.</span><span class="n">wait_for</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">duration</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">ratio</span><span class="o">&lt;</span><span class="mi">1</span><span class="p">,</span><span class="mi">1</span><span class="o">&gt;&gt;::</span><span class="n">max</span><span class="p">()))</span> <span class="p">{</span> <span class="c1">// wait_for return timeout. it means that time period has elapsed.</span> <span class="n">std</span><span class="o">::</span><span class="n">terminate</span><span class="p">();</span> <span class="p">}</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">flag</span><span class="p">)</span> <span class="n">std</span><span class="o">::</span><span class="n">terminate</span><span class="p">();</span> <span class="c1">// we should sleep yet</span> <span class="p">});</span> <span class="n">std</span><span class="o">::</span><span class="n">this_thread</span><span class="o">::</span><span class="n">sleep_for</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">seconds</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="p">{</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_lock</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">l</span><span class="p">(</span><span class="n">sm</span><span class="p">);</span> <span class="n">flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span> <span class="p">}</span> <span class="n">scv</span><span class="p">.</span><span class="n">notify_one</span><span class="p">();</span> <span class="n">t</span><span class="p">.</span><span class="n">join</span><span class="p">();</span> <span class="c1">// test boost</span> <span class="n">boost</span><span class="o">::</span><span class="n">condition_variable</span> <span class="n">bcv</span><span class="p">;</span> <span class="n">boost</span><span class="o">::</span><span class="n">mutex</span> <span class="n">bm</span><span class="p">;</span> <span class="n">flag</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span> <span class="n">std</span><span class="o">::</span><span class="kr">thread</span> <span class="n">bt</span><span class="p">([</span><span class="o">&amp;</span><span class="p">]()</span> <span class="p">{</span> <span class="n">boost</span><span class="o">::</span><span class="n">unique_lock</span><span class="o">&lt;</span><span class="n">boost</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">l</span><span class="p">(</span><span class="n">bm</span><span class="p">);</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">bcv</span><span class="p">.</span><span class="n">timed_wait</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">time_duration</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">pos_infin</span><span class="p">)))</span> <span class="p">{</span> <span class="c1">// timed_wait return false. it means that time period has elapsed.</span> <span class="n">std</span><span class="o">::</span><span class="n">terminate</span><span class="p">();</span> <span class="c1">// positive infinite should never be elapsed</span> <span class="p">}</span> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="n">flag</span><span class="p">)</span> <span class="n">std</span><span class="o">::</span><span class="n">terminate</span><span class="p">();</span> <span class="c1">// we should sleep yet</span> <span class="p">});</span> <span class="n">std</span><span class="o">::</span><span class="n">this_thread</span><span class="o">::</span><span class="n">sleep_for</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">chrono</span><span class="o">::</span><span class="n">seconds</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="p">{</span> <span class="n">boost</span><span class="o">::</span><span class="n">unique_lock</span><span class="o">&lt;</span><span class="n">boost</span><span class="o">::</span><span class="n">mutex</span><span class="o">&gt;</span> <span class="n">l</span><span class="p">(</span><span class="n">bm</span><span class="p">);</span> <span class="n">flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span> <span class="p">}</span> <span class="n">bcv</span><span class="p">.</span><span class="n">notify_one</span><span class="p">();</span> <span class="n">bt</span><span class="p">.</span><span class="n">join</span><span class="p">();</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span> </pre></div></div><p> compiled: MSVS2012 UP4, Win7 Pro. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/9708 Trac 1.4.3 viboes Tue, 25 Feb 2014 06:52:12 GMT owner, status changed https://svn.boost.org/trac10/ticket/9708#comment:1 https://svn.boost.org/trac10/ticket/9708#comment:1 <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> <p> have you tried with </p> <pre class="wiki"> if (boost::cv_status::timeout == scv.wait_for(l, boost::chrono::duration&lt;int, std::ratio&lt;1,1&gt;&gt;::max())) { // wait_for return timeout. it means that time period has elapsed. std::terminate(); } </pre><p> ? </p> Ticket nikolay@… Tue, 25 Feb 2014 07:27:18 GMT <link>https://svn.boost.org/trac10/ticket/9708#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9708#comment:2</guid> <description> <p> bcv.wait_for(l, boost::chrono::duration&lt;int, boost::ratio&lt;1,1&gt;&gt;::max()) works good. </p> <p> But the issue with timed_wait. </p> <p> I have some code like: </p> <div class="wiki-code"><div class="code"><pre><span class="kt">void</span> <span class="nf">foo</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">time_duration</span><span class="o">&amp;</span> <span class="n">td</span><span class="p">)</span> <span class="p">{</span> <span class="p">...</span> <span class="n">cv</span><span class="p">.</span><span class="n">timed_wait</span><span class="p">(...,</span> <span class="n">td</span><span class="p">);</span> <span class="p">...</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">f1</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="n">foo</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">time_duration</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">pos_infin</span><span class="p">));</span> <span class="p">...</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">f2</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="n">foo</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">minutes</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="p">...</span> <span class="p">}</span> <span class="kt">void</span> <span class="nf">f3</span><span class="p">()</span> <span class="p">{</span> <span class="p">...</span> <span class="n">foo</span><span class="p">(</span><span class="n">boost</span><span class="o">::</span><span class="n">posix_time</span><span class="o">::</span><span class="n">milliseconds</span><span class="p">(</span><span class="mi">500</span><span class="p">));</span> <span class="p">...</span> <span class="p">}</span> </pre></div></div> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Thu, 27 Feb 2014 22:23:47 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9708#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9708#comment:3</guid> <description> <p> I suspect that boost::posix_time::pos_infin can be seen as a negative duration. Could you confirm? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Fri, 28 Feb 2014 03:59:38 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9708#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9708#comment:4</guid> <description> <p> boost::posix_time::pos_infin - positive infinity <br /> boost::posix_time::neg_infin - negative infinity </p> <p> time_duration td(pos_infin); <br /> td.is_pos_infinity(); <em> --&gt; true <br /> td.is_negative(); </em> --&gt; false </p> <p> As I see possible this issue may be caused by some changes inside Boost.<a class="missing wiki">DateTime</a> library. I found new note in the Boost.<a class="missing wiki">DateTime</a> documentation: <br /> </p> <blockquote class="citation"> <p> When a time_duration is a special value, either by construction or other means, the following accessor functions will give unpredictable results: hours(), minutes(), seconds(), ticks(), fractional_seconds(), total_nanoseconds(), total_microseconds(), total_milliseconds(), total_seconds() </p> </blockquote> <p> So it seems that Boost.Thread incorrectry call total_milliseconds() inside timed_wait on duration which is special value. Possible code in timed_wait should be like: </p> <div class="wiki-code"><div class="code"><pre> <span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">duration_type</span><span class="o">&gt;</span> <span class="kt">bool</span> <span class="n">timed_wait</span><span class="p">(</span><span class="n">unique_lock</span><span class="o">&lt;</span><span class="n">mutex</span><span class="o">&gt;&amp;</span> <span class="n">m</span><span class="p">,</span><span class="n">duration_type</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">wait_duration</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span> <span class="p">(</span><span class="n">wait_duration</span><span class="p">.</span><span class="n">is_pos_infinity</span><span class="p">())</span> <span class="p">{</span> <span class="n">wait</span><span class="p">(</span><span class="n">m</span><span class="p">);</span> <span class="c1">// or do_wait(m,detail::timeout::sentinel());</span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> <span class="p">}</span> <span class="k">if</span> <span class="p">(</span><span class="n">wait_duration</span><span class="p">.</span><span class="n">is_special_value</span><span class="p">())</span> <span class="p">{</span> <span class="c1">//throw some error</span> <span class="p">}</span> <span class="k">return</span> <span class="n">do_wait</span><span class="p">(</span><span class="n">m</span><span class="p">,</span><span class="n">wait_duration</span><span class="p">.</span><span class="n">total_milliseconds</span><span class="p">());</span> <span class="p">}</span> </pre></div></div> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Fri, 28 Feb 2014 22:19:29 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/9708#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9708#comment:5</guid> <description> <p> timed_value is deprecated. Even if the patch is simple, it is not complete. If you provide a complete patch with tests and the needed documentation I would apply it. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Sat, 01 Mar 2014 07:45:57 GMT</pubDate> <title>type changed https://svn.boost.org/trac10/ticket/9708#comment:6 https://svn.boost.org/trac10/ticket/9708#comment:6 <ul> <li><strong>type</strong> <span class="trac-field-old">Bugs</span> → <span class="trac-field-new">Feature Requests</span> </li> </ul> Ticket viboes Sat, 01 Mar 2014 07:46:39 GMT summary changed https://svn.boost.org/trac10/ticket/9708#comment:7 https://svn.boost.org/trac10/ticket/9708#comment:7 <ul> <li><strong>summary</strong> <span class="trac-field-old">regression: boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite</span> → <span class="trac-field-new">Align to new Boost.DtaeTime behavior (was regression: boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite)</span> </li> </ul> Ticket viboes Sat, 01 Mar 2014 08:16:06 GMT type, summary changed https://svn.boost.org/trac10/ticket/9708#comment:8 https://svn.boost.org/trac10/ticket/9708#comment:8 <ul> <li><strong>type</strong> <span class="trac-field-old">Feature Requests</span> → <span class="trac-field-new">Bugs</span> </li> <li><strong>summary</strong> <span class="trac-field-old">Align to new Boost.DtaeTime behavior (was regression: boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite)</span> → <span class="trac-field-new">was regression: boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite</span> </li> </ul> Ticket viboes Sat, 01 Mar 2014 08:16:39 GMT summary changed https://svn.boost.org/trac10/ticket/9708#comment:9 https://svn.boost.org/trac10/ticket/9708#comment:9 <ul> <li><strong>summary</strong> <span class="trac-field-old">was regression: boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite</span> → <span class="trac-field-new">boost::condition_variable::timed_wait unexpectedly wakes up while should wait infinite</span> </li> </ul> Ticket nikolay@… Mon, 03 Mar 2014 03:54:08 GMT <link>https://svn.boost.org/trac10/ticket/9708#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/9708#comment:10</guid> <description> <p> What is "timed_value"? If you mean "timed_wait" then I have failed to find any notes in the Boost.Thread documentation that this function is deprecated. </p> <p> Anyway currently situation looks like following: </p> <ul><li>there was bug in Boost.Thread in incorrect usage of Boost.<a class="missing wiki">DateTime</a> </li><li>in previous releases it was lucky that code in Boost.Thread works </li><li>in latest releases this issue (incorrect usage of Boost.<a class="missing wiki">DateTime</a>) is not hidden and Boost.Thread code does not work as expected </li><li>Boost.Thread users have an regression after update to the latest boost releases </li><li>I have suggested some changes to fix the problem in the Boost.Thread. I know that it is not final code, but I hope it is a good start point to Boost.Thread authors/sustainers to make an correct and complete changes </li><li>you can fix this issue by any other changes (even with breaking changes), for example, you can always throw something like std::invalid_arg in case if wait_duration.is_special_value(). It is your responsibility to chose correct fix from the view of the Boost.Thread library </li></ul><p> P.S. I am not familiar with git so now I have lose an ability to generate any formal patches to Boost... </p> </description> <category>Ticket</category> </item> <item> <dc:creator>viboes</dc:creator> <pubDate>Wed, 12 Mar 2014 22:50:35 GMT</pubDate> <title>milestone changed https://svn.boost.org/trac10/ticket/9708#comment:11 https://svn.boost.org/trac10/ticket/9708#comment:11 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.56.0</span> </li> </ul> <p> <a class="ext-link" href="https://github.com/boostorg/thread/commit/68dc454a665a54ab505336860401195dc356fd48"><span class="icon">​</span>https://github.com/boostorg/thread/commit/68dc454a665a54ab505336860401195dc356fd48</a> </p> Ticket viboes Wed, 12 Mar 2014 23:01:20 GMT status changed; resolution set https://svn.boost.org/trac10/ticket/9708#comment:12 https://svn.boost.org/trac10/ticket/9708#comment:12 <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> Ticket