简体   繁体   中英

boost timed_wait doesn't wait if date is in 2116 year

The example:

boost::interprocess::interprocess_semaphore semDone(0);
long sec = 10;
boost::posix_time::ptime until = boost::posix_time::second_clock::universal_time() + boost::posix_time::seconds(sec);
bool ret = semDone.timed_wait(until);

It works perfectly on Linux at the time - the timed_wait waits for 10 seconds and then returns false .

However if I move the system date to 2116 year and re-run the app, the timed_wait call returns false immediately. There is the same problem with the boost's condition vars.

Could please anybody explain what's wrong with it?

Info:

  • Linux sles12 3.12.39 x86_64 GNU/Linux
  • g++ 4.8
  • boost 1.54

UPD As I already wrote above, I'm running the test on 64bit platform , and the size of time_t equals 8. So the answers advising to use 64bit time_t instead of 32bit are not applicable for the question.

Let me try to describe what happens with a small stacktrace to the line where the problem occurs (btw, I am using boost 1.58):

#0  boost::interprocess::ipcdetail::ptime_to_timespec (tm=...) at /usr/include/boost/interprocess/sync/posix/ptime_to_timespec.hpp:38
#1  0x402983 in boost::interprocess::ipcdetail::semaphore_timed_wait (handle=0x7fffffffe100, abs_time=...) at /usr/include/boost/interprocess/sync/posix/semaphore_wrapper.hpp:224
#2  0x402ab7 in boost::interprocess::ipcdetail::posix_semaphore::timed_wait (this=0x7fffffffe100, abs_time=...) at /usr/include/boost/interprocess/sync/posix/semaphore.hpp:55
#3  0x402b1d in boost::interprocess::interprocess_semaphore::timed_wait (this=0x7fffffffe100, abs_time=...) at /usr/include/boost/interprocess/sync/interprocess_semaphore.hpp:139
#4  0x40184d in main () at /tmp/t.cpp:10

Ok, so lets have a look what happens in the method ptime_to_timespec. Your previously created ptime object (line 3)

boost::posix_time::ptime until = boost::posix_time::second_clock::universal_time() + boost::posix_time::seconds(sec);

is passed to this function and is converted into a timespec object. The timespec object is defined in time.h and can be used to compute the duration since 00:00:00 January 1, 1970. (see http://pubs.opengroup.org/onlinepubs/7908799/xsh/time.h.html ) It contains members like tv_sec (duration in seconds, type time_t), tv_nsec (type long), etc.

The problem simply is that the duration in seconds (starting at 01/01/1970 and ending at XX/XX/2116) is too large and does not fit into tv_sec (time_t is basically a signed int). The problem is also described here: https://stackoverflow.com/a/471287/5967798

I tested it with year 2116 and the timespec that was returned by the function described the date 9:18:59 am CET | Wednesday, October 8, 1980 9:18:59 am CET | Wednesday, October 8, 1980

The root cause of the problem is that boost::posix_time::time_duration::total_seconds() explicitly casts the return value to time_resolution_traits::sec_type while converting ptime to timespec via boost::interprocess::ipcdetail::ptime_to_timespec() during the timed_wait() call. The time_resolution_traits::sec_type is a typedef to int32_t type (see the typedef chain in boost/date_time/time_resolution_traits.hpp file).

At the same time documentation says that time_duration::total_seconds() returns long ( http://www.boost.org/doc/libs/1_62_0/doc/html/date_time/posix_time.html ). But for LP64 models (eg Linux, 64bit) it returns signed 32bit integer, not long (signed 64bit integer).

So obviously there is a bug in boost . The first ticket for the bug was created in 2009. And it is still not fixed.

The tickets:


UPD : The bug was fixed in Boost 1.66 as it's described at the bug's comments.

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