From f54e5f305973309f6fb7d092cd3681ec371b4f4a Mon Sep 17 00:00:00 2001 From: brarcher Date: Sat, 21 Sep 2013 16:33:08 +0000 Subject: [PATCH] Use setitimer in timer_* fallbacks CCurrently on GNU/Hurd the timer_* functions are not implemented; check's configure detects that and switches to the replacements functions in lib/, which use alarm for the timer. However, using alarm does not allow a timeout precision more than 1 second (as also written in the comments in lib/timer_settime.c), causing the failure of the two tests check_check_export and check_check. As a workaround, it is possible to get a better precision using the POSIX function setitimer [1] (declared obsolescent, but still usable) instead of alarm. This change checks for the existence of setitimer, and in case it exists uses it (with its ITIMER_REAL timer) in the replacement timer_settime and timer_delete. Given they are implemented in the Hurd, all the tests of check passes. [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/getitimer.html Patch submitted by Pino Toscano, patch#49 git-svn-id: svn+ssh://svn.code.sf.net/p/check/code/trunk@759 64e312b2-a51f-0410-8e61-82d0ca0eb02a --- AUTHORS | 1 + NEWS | 4 ++++ configure.ac | 2 ++ lib/timer_delete.c | 18 ++++++++++++++++++ lib/timer_settime.c | 15 +++++++++++++++ 5 files changed, 40 insertions(+) diff --git a/AUTHORS b/AUTHORS index 3002779..ff78f54 100644 --- a/AUTHORS +++ b/AUTHORS @@ -41,6 +41,7 @@ Contributors: Sebastian Rasmussen (duration bug fix, 64-bit API fix) Martin Willers (rename check's internal list API to start with check_) bross (patches for msys/mingw32 support) + Pino Toscano (GNU/Hurd support for subsecond timeouts) Anybody who has contributed code to Check or Check's build system is considered an author. Send patches to this file to diff --git a/NEWS b/NEWS index bbec284..43ae88e 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ In development: * Check compiles for the Windows using x86_64-w64-mingw32. +* On systems without timer_settimer, use setitimer (if available) to get + subsecond unit test timeouts. If setitimer is unavailable, fallback + on alarm. + Thu, Apr 18, 2013: Released Check 0.9.10 based on r743 (2013-04-18 11:27:03 +0200) diff --git a/configure.ac b/configure.ac index 0d8c80d..9f71098 100644 --- a/configure.ac +++ b/configure.ac @@ -184,6 +184,8 @@ AC_FUNC_REALLOC AC_REPLACE_FUNCS([alarm clock_gettime timer_create timer_settime timer_delete fileno localtime_r pipe putenv setenv sleep strdup strsignal unsetenv]) AC_CHECK_DECLS([alarm, clock_gettime, timer_create, timer_settime, timer_delete, fileno, localtime_r, pipe, putenv, setenv, sleep, strdup, strsignal, unsetenv]) +AC_CHECK_FUNCS([setitimer]) + # Check if the system's snprintf (and its variations) are C99 compliant. # If they are not, use the version in libcompat. HW_FUNC_VSNPRINTF diff --git a/lib/timer_delete.c b/lib/timer_delete.c index 4228b37..02cf16b 100644 --- a/lib/timer_delete.c +++ b/lib/timer_delete.c @@ -2,6 +2,23 @@ int timer_delete(timer_t timerid CK_ATTRIBUTE_UNUSED) { +#ifdef HAVE_SETITIMER + /* + * If the system does not have timer_settime() but does have + * setitimer() use that instead of alarm(). + */ + struct itimerval new; + + /* + * Setting values to '0' results in disabling the running timer. + */ + new.it_value.tv_sec = 0; + new.it_value.tv_usec = 0; + new.it_interval.tv_sec = 0; + new.it_interval.tv_usec = 0; + + return setitimer(ITIMER_REAL, &new, NULL); +#else /* * There is only one timer, that used by alarm. * Setting alarm(0) will not set a new alarm, and @@ -11,4 +28,5 @@ int timer_delete(timer_t timerid CK_ATTRIBUTE_UNUSED) alarm(0); return 0; +#endif } diff --git a/lib/timer_settime.c b/lib/timer_settime.c index 39ec613..963830a 100644 --- a/lib/timer_settime.c +++ b/lib/timer_settime.c @@ -5,6 +5,20 @@ int timer_settime(timer_t timerid CK_ATTRIBUTE_UNUSED, const struct itimerspec *new_value, struct itimerspec * old_value CK_ATTRIBUTE_UNUSED) { +#ifdef HAVE_SETITIMER + /* + * If the system does not have timer_settime() but does have + * setitimer() use that instead of alarm(). + */ + struct itimerval new; + + new.it_value.tv_sec = new_value->it_value.tv_sec; + new.it_value.tv_usec = new_value->it_value.tv_nsec / 1000; + new.it_interval.tv_sec = new_value->it_interval.tv_sec; + new.it_interval.tv_usec = new_value->it_interval.tv_nsec / 1000; + + return setitimer(ITIMER_REAL, &new, NULL); +#else int seconds = new_value->it_value.tv_sec; /* @@ -19,4 +33,5 @@ int timer_settime(timer_t timerid CK_ATTRIBUTE_UNUSED, alarm(seconds); return 0; +#endif } -- 2.50.1