diff --git a/configure/CONFIG b/configure/CONFIG
index 17440a39e..580b58767 100644
--- a/configure/CONFIG
+++ b/configure/CONFIG
@@ -73,17 +73,17 @@ ifdef T_A
#
-include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).$(T_A)
+ # Site specific target and host-target definitions and overrides
+ #
+ -include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
+ -include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
+
# RELEASE file specific definitions
#
ifneq ($(CONFIG),$(TOP)/configure)
-include $(CONFIG)/CONFIG_APP_INCLUDE
endif
- # Site specific target and host-target definitions
- #
- -include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
- -include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
-
endif # ifdef T_A
diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html
index 7c5ade339..111c604d3 100644
--- a/documentation/RELEASE_NOTES.html
+++ b/documentation/RELEASE_NOTES.html
@@ -597,6 +597,17 @@ tells git to ignore all configure/*.local files.
+Extend maximum Posix epicsEventWaitWithTimeout() delay
+
+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
+time_t 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.
+
New test-related make targets
This release adds several new make targets intended for use by developers
diff --git a/src/libCom/fdmgr/fdManager.cpp b/src/libCom/fdmgr/fdManager.cpp
index ff5022d81..00f4d4a87 100644
--- a/src/libCom/fdmgr/fdManager.cpp
+++ b/src/libCom/fdmgr/fdManager.cpp
@@ -113,7 +113,7 @@ epicsShareFunc void fdManager::process (double delay)
if ( ioPending ) {
struct timeval tv;
- tv.tv_sec = static_cast ( minDelay );
+ tv.tv_sec = static_cast ( minDelay );
tv.tv_usec = static_cast ( (minDelay-tv.tv_sec) * uSecPerSec );
fd_set * pReadSet = & this->fdSetsPtr[fdrRead];
diff --git a/src/libCom/osi/os/Darwin/osdTime.cpp b/src/libCom/osi/os/Darwin/osdTime.cpp
index c4a7e838c..72b3dc874 100644
--- a/src/libCom/osi/os/Darwin/osdTime.cpp
+++ b/src/libCom/osi/os/Darwin/osdTime.cpp
@@ -68,14 +68,14 @@ convertDoubleToWakeTime(double timeout, struct timespec *wakeTime)
mach_timespec_t now;
struct timespec wait;
+ if (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);
- if (timeout<0.0)
- timeout = 0.0;
- else if(timeout>3600.0)
- timeout = 3600.0;
-
- wait.tv_sec = static_cast< long >(timeout);
+ wait.tv_sec = static_cast< time_t >(timeout);
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
wakeTime->tv_sec = now.tv_sec + wait.tv_sec;
diff --git a/src/libCom/osi/os/posix/osdTime.cpp b/src/libCom/osi/os/posix/osdTime.cpp
index 2d98cf3ae..d5fb05a1c 100644
--- a/src/libCom/osi/os/posix/osdTime.cpp
+++ b/src/libCom/osi/os/posix/osdTime.cpp
@@ -88,30 +88,35 @@ int epicsTime_localtime ( const time_t *clock,
extern "C" epicsShareFunc void
convertDoubleToWakeTime(double timeout,struct timespec *wakeTime)
{
- struct timespec wait;
+ struct timespec now, wait;
int status;
- if(timeout<0.0) timeout = 0.0;
- else if(timeout>3600.0) timeout = 3600.0;
+ if (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
- status = clock_gettime(CLOCK_REALTIME, wakeTime);
+ status = clock_gettime(CLOCK_REALTIME, &now);
#else
{
struct timeval tv;
struct timezone tz;
status = gettimeofday(&tv, &tz);
- wakeTime->tv_sec = tv.tv_sec;
- wakeTime->tv_nsec = tv.tv_usec * 1000;
+ now.tv_sec = tv.tv_sec;
+ now.tv_nsec = tv.tv_usec * 1000;
}
#endif
if (status) {
perror("convertDoubleToWakeTime");
cantProceed("convertDoubleToWakeTime");
}
- wait.tv_sec = static_cast< long >(timeout);
+
+ wait.tv_sec = static_cast< time_t >(timeout);
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) {
wakeTime->tv_nsec -= 1000000000L;
++wakeTime->tv_sec;
diff --git a/src/libCom/test/epicsTimeTest.cpp b/src/libCom/test/epicsTimeTest.cpp
index ec5da4c78..55ad43cdd 100644
--- a/src/libCom/test/epicsTimeTest.cpp
+++ b/src/libCom/test/epicsTimeTest.cpp
@@ -43,7 +43,7 @@ MAIN(epicsTimeTest)
const int wasteTime = 100000;
const int nTimes = 10;
- testPlan(15 + nTimes * 19);
+ testPlan(17 + nTimes * 19);
try {
const epicsTimeStamp epochTS = {0, 0};
@@ -211,5 +211,35 @@ MAIN(epicsTimeTest)
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();
}
diff --git a/src/libCom/test/fdmgrTest.c b/src/libCom/test/fdmgrTest.c
index 86857c6f5..e41784ccf 100644
--- a/src/libCom/test/fdmgrTest.c
+++ b/src/libCom/test/fdmgrTest.c
@@ -74,13 +74,13 @@ void testTimer (fdctx *pfdm, double delay)
epicsTimeGetCurrent (&begin);
cbs.done = 0;
- tmo.tv_sec = (unsigned long) delay;
+ tmo.tv_sec = (time_t) delay;
tmo.tv_usec = (unsigned long) ((delay - tmo.tv_sec) * uSecPerSec);
aid = fdmgr_add_timeout (pfdm, &tmo, alarmCB, &cbs);
verify (aid!=fdmgrNoAlarm);
while (!cbs.done) {
- tmo.tv_sec = (unsigned long) delay;
+ tmo.tv_sec = (time_t) delay;
tmo.tv_usec = (unsigned long) ((delay - tmo.tv_sec) * uSecPerSec);
status = fdmgr_pend_event (pfdm, &tmo);
verify (status==0);
diff --git a/src/libCom/timer/timerPrivate.h b/src/libCom/timer/timerPrivate.h
index c60939851..55291309c 100644
--- a/src/libCom/timer/timerPrivate.h
+++ b/src/libCom/timer/timerPrivate.h
@@ -105,7 +105,7 @@ private:
epicsTime exceptMsgTimeStamp;
bool cancelPending;
static const double exceptMsgMinPeriod;
- void printExceptMsg ( const char * pName,
+ void printExceptMsg ( const char * pName,
const type_info & type );
timerQueue ( const timerQueue & );
timerQueue & operator = ( const timerQueue & );