简体   繁体   中英

Boost timed_wait leap seconds problem

I am using the timed_wait from boost C++ library and I am getting a problem with leap seconds.

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 is returning 24 seconds earlier than it should. 24 seconds is the current amount of leap seconds in UTC.

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

Notes: I am using boost 1.38 on a linux system. I've heard that this problem doesn't happen on MacOS.

UPDATE: A little more info: This is happening on 2 redhat machines with kernel 2.6.9. I have executed the same code on an ubuntu machine with kernel 2.6.30 and the timer behaves as expected.

So, what I think is that this is probably being caused by the OS or by some mis-set configuration on the redhat machines.

I have coded a workaround that adjusts the time to UTC and than get the difference from this adjustment and add to the original time. This seens like a bad idea to me because if this code is executed on a machine without this problem, it might be 24s AHEAD. Still could not find the reason for this.

On a Linux system, the system clock will follow the POSIX standard, which mandates that leap seconds are NOT observed! If you expected otherwise, that's probably the source of the discrepancy you're seeing. This document has a great explanation of how UTC relates to other time scales, and the problems one is likely to encounter if one relies on the operating system's concept of timekeeping.

是否有可能提前设置完成并且虚假唤醒导致循环比您预期的更快退出?

Ok, here is what I did. It's a workaround and I am not happy with it 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've tested it on problematic and non-problematic machines and it worked as expected on both, so I'm keeping it as long as I can't found a better solution.

Thank you all for your help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM