The following behavior was seen under g 11.2.1 . The std::condition_variable
wait_for
method returns immediately if the timeout variable is too large. In particular in the program below, if num_years==1
, then the program hangs waiting as expected (presumably for 1 year), but if the variable num_years==1000
then the program returns immediatly.
Why does this happen? Is this a bug in g ? And a related question, how do you make the cv.wait_for()
wait indefinitely, instead of guessing a large timeout value?
// This is 'cv_wait.cc' compile with:
//
// g -o cv_wait -std=c 2a cv_wait.cc
//
// An example showing that wait_for() returns immediately with a timeout
// return value if the duration variable is "too large".
//
#include <iostream>
#include <condition_variable>
#include <chrono>
int main(int argc, char **argv)
{
std::condition_variable cv;
std::mutex cv_m;
// If num_years is "too large", e.g. 1000, then cv.wait_for()
// returns immediately with a timeout condition!
int num_years = 1; // If 1000 then cv.wait_for() returns immediately!
std::chrono::seconds timeout((uint64_t)3600 * 24 * 365 * num_years);
std::unique_lock<std::mutex> lock(cv_m);
if (cv.wait_for(lock, timeout, [] { return false; }))
std::cerr << "No timeout!\n";
else
std::cerr << "Timeout!\n";
}
CodePudding user response:
This is an overflow bug under the hood of condition_variable::wait_for
. Internally it is waiting using steady_clock
which counts nanoseconds
. This clock overflows at /-292 years. So when 1000 years gets converted to nanoseconds
, it is overflowing.
This looks like a standards bug as opposed to an implementation bug: http://eel.is/c draft/thread.condition#condvar-24
The implementation should check for overflows of this type and in case found, just wait for the maximum time it is capable of waiting for.