Subject: Re: bug#9101: timeout should use setitimer if available

From: Pádraig Brady <[email-masked]>
Date: Tue, 19 Jul 2011 12:00:23 +0100

On 18/07/11 23:17, Pádraig Brady wrote:
> On 18/07/11 17:44, Paul Eggert wrote:
>> On 07/18/11 03:01, Pádraig Brady wrote:
>>> I'll apply this soon.
>>
>> Thanks for doing that. Some comments:
>>
>> I see that my bug report was incoherent, as it was talking about
>> nanosecond resolution and setitimer, when I meant to be writing about
>> timer_settime (which *does* have nanosecond resolution).  Sorry about
>> that.
>>
>> POSIX says that setitimer is obsolescent, and that applications should use
>> timer_settime.  How about if we add a gnulib module for timer_settime
>> and have 'timeout' use that instead?  (This could be a separate patch,
>> done later.)
> 
> Hmm. We don't need the extra resolution or functionality of timer_settime().
> So I prefer the simplier setitimer() interface TBH.
> Currently, setitimer should be more portable too, I guess.
> No rush with timer_settime() I think.

Note the main current platform missing timer_settimer is darwin.

Using timer_settimer isn't that onerous actually.
The gnulib check could be lumped into clock_time, like:

diff --git a/m4/clock_time.m4 b/m4/clock_time.m4
index 3c08512..344d330 100644
--- a/m4/clock_time.m4
+++ b/m4/clock_time.m4
@@ -4,7 +4,7 @@ dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.

-# Check for clock_gettime and clock_settime, and set LIB_CLOCK_GETTIME.
+# Check for clock_[gs]ettime and timer_settime, and set LIB_CLOCK_GETTIME.
 # For a program named, say foo, you should add a line like the following
 # in the corresponding Makefile.am file:
 # foo_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
@@ -26,6 +26,6 @@ AC_DEFUN([gl_CLOCK_TIME],
     AC_SEARCH_LIBS([clock_gettime], [rt posix4],
                    [test "$ac_cv_search_clock_gettime" = "none required" ||
                     LIB_CLOCK_GETTIME=$ac_cv_search_clock_gettime])
-    AC_CHECK_FUNCS([clock_gettime clock_settime])
+    AC_CHECK_FUNCS([clock_gettime clock_settime timer_settime])
   LIBS=$gl_saved_libs
 ])

And coreutils could use it like:

diff --git a/src/Makefile.am b/src/Makefile.am
index ef0e7a4..76cee0d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -329,6 +329,7 @@ date_LDADD += $(LIB_CLOCK_GETTIME)
 ginstall_LDADD += $(LIB_CLOCK_GETTIME)
 ls_LDADD += $(LIB_CLOCK_GETTIME)
 pr_LDADD += $(LIB_CLOCK_GETTIME)
+timeout_LDADD += $(LIB_CLOCK_GETTIME)
 touch_LDADD += $(LIB_CLOCK_GETTIME)

 # for gethrxtime
diff --git a/src/timeout.c b/src/timeout.c
index bfca548..8b5ff8d 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -105,7 +105,15 @@ static struct option const long_options[] =
 static void
 settimeout (double duration)
 {
-#if HAVE_SETITIMER
+#if HAVE_TIMER_SETTIME
+  struct timespec ts = dtotimespec (duration);
+  struct itimerspec its = { {0, 0}, ts };
+  timer_t timerid;
+  if (timer_create (CLOCK_REALTIME, NULL, &timerid) == -1)
+    error (EXIT_FAILURE, errno, _("error in timer_create"));
+  if (timer_settime (timerid, 0, &its, NULL) == -1)
+    error (EXIT_FAILURE, errno, _("error in timer_settime"));
+#elif HAVE_SETITIMER
   struct timeval tv;
   struct timespec ts = dtotimespec (duration);
   tv.tv_usec = (ts.tv_nsec + 999) / 1000;

We could remove the setitimer stuff altogether and
just support 1 second resolution on darwin et. al.
That's by far the most common use case anyway.

cheers,
Pádraig.