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.
Advertisement
Answer
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 (e.g. 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:
https://svn.boost.org/trac/boost/ticket/12214
I created the new one: https://svn.boost.org/trac/boost/ticket/12609.
UPD: The bug was fixed in Boost 1.66 as it’s described at the bug’s comments.