Subject: Re: [Boost-bugs] [Boost C++ Libraries] #9856: [windows] condition_variable::wait_for returns wrong cv_status on timeout.
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-01-22 18:38:11
#9856: [windows] condition_variable::wait_for returns wrong cv_status on timeout.
-------------------------+-------------------------------------------------
Reporter: pi88el@⦠| Owner: ned14
Type: Bugs | Status: new
Milestone: | Component: thread
Version: Boost | Severity: Problem
1.57.0 | Keywords: condition_variable wait_for
Resolution: | cv_status
-------------------------+-------------------------------------------------
Comment (by ned14):
I have an update on this issue. Firstly, I have committed a testcase for
this to Boost.Thread trunk, so it is now being tested as part of regular
unit testing.
I have some quite scary news though. Boost.Thread decides whether the wait
has timed out by comparing steady_clock (really QueryPerformanceCounter)
from before and after, and if the wait took the timeout or longer it
assumes that timeout occurred. Unfortunately, WaitForMultipleObjectsEx()
provides no guarantees that it actually waits for the timeout requested -
you might request 50ms, but might actually get 10ms. Here is an example
program:
{{{
#include <windows.h>
#include <stdio.h>
#include <chrono>
int main(void)
{
ULONG ulDelay_ms = 20;
HANDLE hSemaphoreDelay = CreateSemaphore(NULL, 0, 1, NULL);
for (size_t n = 0; n < 50; n++)
{
while (1) {
auto begin = std::chrono::high_resolution_clock::now();
ULONG hr = WaitForSingleObject(hSemaphoreDelay, ulDelay_ms);
auto end = std::chrono::high_resolution_clock::now();
auto diff = end - begin;
if (hr == WAIT_ABANDONED)
printf("Wait Abandoned ");
else if (hr == WAIT_TIMEOUT)
printf("Timed out ");
else
printf("Signaled ");
DWORD lTDelta =
std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();
printf("Target Wait Interval: %u Real Wait Interval: %u (%u)\n",
ulDelay_ms, lTDelta, diff.count());
if (lTDelta >= ulDelay_ms) break;
}
printf("\n");
}
CloseHandle(hSemaphoreDelay);
return 0;
}
}}}
... and indeed very occasionally it is returning after 16-18ms instead of
the requested 20ms at the same frequency that Boost.Thread is not
returning timeout.
This is scary because I believe every single wait routine in Windows in
Boost.Thread, and possibly other Boost libraries, will need to be audited
and potentially refactored. I'll raise it on boost-dev tomorrow morning. I
believe this new early timeout feature was probably introduced when
Microsoft added timer coalescing to Windows to save battery on mobile
devices, and so only appeared in Windows 7 and later. The fact it hasn't
presented sooner is worrying.
Niall
-- Ticket URL: <https://svn.boost.org/trac/boost/ticket/9856#comment:16> Boost C++ Libraries <http://www.boost.org/> Boost provides free peer-reviewed portable C++ source libraries.
This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:17 UTC