Posix epicsEventWaitWithTimeout() max delay
Limit timeouts on Posix to max-out at 10 years. Adds a test that will fail when that time-out hits Y2038 on systems where time_t is still a 32-bit integer.
This commit is contained in:
@@ -13,6 +13,16 @@
|
|||||||
|
|
||||||
<!-- Insert new items immediately below here ... -->
|
<!-- Insert new items immediately below here ... -->
|
||||||
|
|
||||||
|
<h3>Extend maximum Posix epicsEventWaitWithTimeout() delay</h3>
|
||||||
|
|
||||||
|
<p>The Posix implementation of epicsEventWaitWithTimeout() was limiting the
|
||||||
|
timeout delay to at most 60 minutes (3600.0 seconds). This has been changed to
|
||||||
|
10 years; significantly longer maximum delays cause problems on systems where
|
||||||
|
<tt>time_t</tt> is still a signed 32-bit integer so cannot represent absolute
|
||||||
|
time-stamps after 2038-01-19. Our assumption is that such 32-bit systems will
|
||||||
|
have been retired before the year 2028, but some additional tests have been
|
||||||
|
added to the epicsTimeTest program to detect and fail if this assumption is
|
||||||
|
violated.</p>
|
||||||
|
|
||||||
<h3>New test-related make targets</h3>
|
<h3>New test-related make targets</h3>
|
||||||
|
|
||||||
|
|||||||
@@ -67,10 +67,12 @@ convertDoubleToWakeTime(double timeout, struct timespec *wakeTime)
|
|||||||
mach_timespec_t now;
|
mach_timespec_t now;
|
||||||
struct timespec wait;
|
struct timespec wait;
|
||||||
|
|
||||||
clock_get_time(host_clock, &now);
|
|
||||||
|
|
||||||
if (timeout < 0.0)
|
if (timeout < 0.0)
|
||||||
timeout = 0.0;
|
timeout = 0.0;
|
||||||
|
else if (timeout > 60 * 60 * 24 * 3652.5)
|
||||||
|
timeout = 60 * 60 * 24 * 3652.5; /* 10 years */
|
||||||
|
|
||||||
|
clock_get_time(host_clock, &now);
|
||||||
|
|
||||||
wait.tv_sec = static_cast< time_t >(timeout);
|
wait.tv_sec = static_cast< time_t >(timeout);
|
||||||
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
|
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
|
||||||
|
|||||||
@@ -87,30 +87,35 @@ int epicsTime_localtime ( const time_t *clock, // X aCC 361
|
|||||||
extern "C" epicsShareFunc void
|
extern "C" epicsShareFunc void
|
||||||
convertDoubleToWakeTime(double timeout,struct timespec *wakeTime)
|
convertDoubleToWakeTime(double timeout,struct timespec *wakeTime)
|
||||||
{
|
{
|
||||||
struct timespec wait;
|
struct timespec now, wait;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (timeout < 0.0)
|
if (timeout < 0.0)
|
||||||
timeout = 0.0;
|
timeout = 0.0;
|
||||||
|
else if (timeout > 60 * 60 * 24 * 3652.5)
|
||||||
|
timeout = 60 * 60 * 24 * 3652.5; /* 10 years */
|
||||||
|
|
||||||
#ifdef CLOCK_REALTIME
|
#ifdef CLOCK_REALTIME
|
||||||
status = clock_gettime(CLOCK_REALTIME, wakeTime);
|
status = clock_gettime(CLOCK_REALTIME, &now);
|
||||||
#else
|
#else
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
struct timezone tz;
|
struct timezone tz;
|
||||||
status = gettimeofday(&tv, &tz);
|
status = gettimeofday(&tv, &tz);
|
||||||
wakeTime->tv_sec = tv.tv_sec;
|
now.tv_sec = tv.tv_sec;
|
||||||
wakeTime->tv_nsec = tv.tv_usec * 1000;
|
now.tv_nsec = tv.tv_usec * 1000;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (status) {
|
if (status) {
|
||||||
perror("convertDoubleToWakeTime");
|
perror("convertDoubleToWakeTime");
|
||||||
cantProceed("convertDoubleToWakeTime");
|
cantProceed("convertDoubleToWakeTime");
|
||||||
}
|
}
|
||||||
|
|
||||||
wait.tv_sec = static_cast< time_t >(timeout);
|
wait.tv_sec = static_cast< time_t >(timeout);
|
||||||
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
|
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
|
||||||
wakeTime->tv_sec += wait.tv_sec;
|
|
||||||
wakeTime->tv_nsec += wait.tv_nsec;
|
wakeTime->tv_sec = now.tv_sec + wait.tv_sec;
|
||||||
|
wakeTime->tv_nsec = now.tv_nsec + wait.tv_nsec;
|
||||||
if (wakeTime->tv_nsec >= 1000000000L) {
|
if (wakeTime->tv_nsec >= 1000000000L) {
|
||||||
wakeTime->tv_nsec -= 1000000000L;
|
wakeTime->tv_nsec -= 1000000000L;
|
||||||
++wakeTime->tv_sec;
|
++wakeTime->tv_sec;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ MAIN(epicsTimeTest)
|
|||||||
const int wasteTime = 100000;
|
const int wasteTime = 100000;
|
||||||
const int nTimes = 10;
|
const int nTimes = 10;
|
||||||
|
|
||||||
testPlan(15 + nTimes * 19);
|
testPlan(17 + nTimes * 19);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const epicsTimeStamp epochTS = {0, 0};
|
const epicsTimeStamp epochTS = {0, 0};
|
||||||
@@ -216,5 +216,35 @@ MAIN(epicsTimeTest)
|
|||||||
testOk1(beginTS + diff == now);
|
testOk1(beginTS + diff == now);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
epicsTime ten_years_hence;
|
||||||
|
try {
|
||||||
|
now = epicsTime::getCurrent();
|
||||||
|
ten_years_hence = now + 60 * 60 * 24 * 3652.5;
|
||||||
|
testPass("epicsTime can represent 10 years hence");
|
||||||
|
}
|
||||||
|
catch ( ... ) {
|
||||||
|
testFail("epicsTime exception for value 10 years hence");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
/* This test exists because in libCom/osi/os/posix/osdTime.cpp
|
||||||
|
* the convertDoubleToWakeTime() routine limits the timeout delay
|
||||||
|
* to 10 years. libCom/timer/timerQueue.cpp returns DBL_MAX for
|
||||||
|
* queues with no timers present, and convertDoubleToWakeTime()
|
||||||
|
* has to return an absolute Posix timestamp. On 2028-01-19 any
|
||||||
|
* systems that still implement time_t as a signed 32-bit integer
|
||||||
|
* will be unable to represent that timestamp, so this will fail.
|
||||||
|
*/
|
||||||
|
time_t_wrapper os_time_t = ten_years_hence;
|
||||||
|
epicsTime then = os_time_t; // No fractional seconds
|
||||||
|
double delta = ten_years_hence - then;
|
||||||
|
|
||||||
|
testOk(delta >= 0 && delta < 1.0,
|
||||||
|
"OS time_t can represent 10 years hence");
|
||||||
|
}
|
||||||
|
catch ( ... ) {
|
||||||
|
testFail("OS time_t conversion exception for value 10 years hence");
|
||||||
|
}
|
||||||
|
|
||||||
return testDone();
|
return testDone();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user