Boost timed_wait leap seconds problem

I am using timed_wait from the C ++ boost library and I am having a problem with stopwatch.

Here is a quick test:

#include <boost/thread.hpp> #include <stdio.h> #include <boost/date_time/posix_time/posix_time.hpp> int main(){ // Determine the absolute time for this timer. boost::system_time tAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(35000); bool done; boost::mutex m; boost::condition_variable cond; boost::unique_lock<boost::mutex> lk(m); while(!done) { if(!cond.timed_wait(lk,tAbsoluteTime)) { done = true; std::cout << "timed out"; } } return 1; } 

The timed_wait function returns 24 seconds earlier than necessary. 24 seconds is the current number of seconds of jump in UTC.

So, boost is widely used, but I could not find any information about this particular problem. Has anyone else experienced this issue? What are the possible causes and solutions?

Notes: I am using boost 1.38 on a Linux system. I heard that this problem does not occur on macOS.

UPDATE: a little more information: this happens on 2 redhat machines with a 2.6.9 kernel. I ran the same code on an ubuntu machine with a 2.6.30 kernel, and the timer behaves as expected.

So, I think this is probably caused by the OS or some misconfiguration on redhat machines.

I encoded a workaround that sets the time to UTC and then gets the difference from this setting and adds to the original time. This seems like a bad idea to me, because if this code is executed on a machine without this problem, it could be 24 Ahad. Still unable to find the reason for this.

+4
source share
3 answers

Ok, that’s what I did. This is a workaround, and I'm not happy with that, but it was the best I could come up with:

 int main(){ typedef boost::date_time::c_local_adjustor<boost::system_time> local_adj; // Determine the absolute time for this timer. boost::system_time tAbsoluteTime = boost::get_system_time() + boost::posix_time::milliseconds(25000); /* * A leap second is a positive or negative one-second adjustment to the Coordinated * Universal Time (UTC) time scale that keeps it close to mean solar time. * UTC, which is used as the basis for official time-of-day radio broadcasts for civil time, * is maintained using extremely precise atomic clocks. To keep the UTC time scale close to * mean solar time, UTC is occasionally corrected by an adjustment, or "leap", * of one second. */ boost::system_time tAbsoluteTimeUtc = local_adj::utc_to_local(tAbsoluteTime); // Calculate the local-to-utc difference. boost::posix_time::time_duration tLocalUtcDiff = tAbsoluteTime - tAbsoluteTimeUtc; // Get only the seconds from the difference. These are the leap seconds. tAbsoluteTime += boost::posix_time::seconds(tLocalUtcDiff.seconds()); bool done; boost::mutex m; boost::condition_variable cond; boost::unique_lock<boost::mutex> lk(m); while(!done) { if(!cond.timed_wait(lk,tAbsoluteTime)) { done = true; std::cout << "timed out"; } } return 1; } 

I tested it on problematic and non-problematic machines, and it worked as expected on both, so I save it until I can find a better solution.

Thank you all for your help.

0
source

On Linux, the system clock will follow the POSIX standard, which stipulates that seconds of jump are not observed! If you expected otherwise, this is probably the source of the inconsistency that you see. This document has a great explanation of how UTC relates to other time scales, and the problems you are likely to encounter if you rely on the operating system for the timing concept.

+2
source

Is it possible that this is done prematurely, and a false awakening leads to the fact that the cycle leaves earlier than you expected?

+1
source

Source: https://habr.com/ru/post/1309056/


All Articles