]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lib/timer: add fallback if timer_create() not available
authorKarel Zak <kzak@redhat.com>
Wed, 24 Oct 2018 10:28:13 +0000 (12:28 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Dec 2018 10:23:33 +0000 (11:23 +0100)
* add struct ul_timer as API abstraction to hide differences between
timer_create() and setitimer()

* add setitimer() detection to ./configure.ac

* add fallback code to use setitimer() if timer_create() not available
  (for example on OSX)

Addresses: https://github.com/karelzak/util-linux/issues/584
Signed-off-by: Karel Zak <kzak@redhat.com>
configure.ac
include/timer.h
lib/timer.c
misc-utils/uuidd.c
sys-utils/flock.c

index 21b04f5817f6f1a9cd8785973cc5092a2830162f..e6cfd4605cce28c7e15bdba1b03a01409d4b9a1a 100644 (file)
@@ -558,6 +558,10 @@ AC_CHECK_FUNCS([timer_create],
 
 AC_SUBST([REALTIME_LIBS])
 
+AS_IF([test x"$have_timer" = xno], [
+       AC_CHECK_FUNCS([setitimer], [have_timer="yes"], [have_timer="no"])
+])
+
 
 AC_CHECK_LIB([rtas], [rtas_get_sysparm], [
        RTAS_LIBS="-lrtas"
index aa9f9c0186e8903ba0687a55cf819d229bf5755c..70da1ba9e3b97e5b3c3362d7230c045a1a00ec6c 100644 (file)
@@ -4,8 +4,19 @@
 #include <signal.h>
 #include <sys/time.h>
 
-extern int setup_timer(timer_t * t_id, struct itimerval *timeout,
+#ifdef HAVE_TIMER_CREATE
+struct ul_timer {
+       timer_t t_id;
+};
+#else
+struct ul_timer {
+       struct itimerval old_timer;
+       struct sigaction old_sa;
+};
+#endif
+
+extern int setup_timer(struct ul_timer *timer, struct itimerval *timeout,
                       void (*timeout_handler)(int, siginfo_t *, void *));
-extern void cancel_timer(timer_t * t_id);
+extern void cancel_timer(struct ul_timer *timer);
 
 #endif /* UTIL_LINUX_TIMER_H */
index 210c726cbe5ade41c0ca0b158f6b22c5aa713077..c1ea54eb828d43b4c0d73cb076a37b2d3952a07d 100644 (file)
@@ -27,7 +27,9 @@
  * The applications need to ensure that they can tolerate multiple signal
  * deliveries.
  */
-int setup_timer(timer_t * t_id, struct itimerval *timeout,
+#ifdef HAVE_TIMER_CREATE
+int setup_timer(struct ul_timer *timer,
+               struct itimerval *timeout,
                void (*timeout_handler)(int, siginfo_t *, void *))
 {
        time_t sec = timeout->it_value.tv_sec;
@@ -52,14 +54,42 @@ int setup_timer(timer_t * t_id, struct itimerval *timeout,
 
        if (sigaction(SIGALRM, &sig_a, NULL))
                return 1;
-       if (timer_create(CLOCK_MONOTONIC, &sig_e, t_id))
+       if (timer_create(CLOCK_MONOTONIC, &sig_e, &timer->t_id))
                return 1;
-       if (timer_settime(*t_id, 0, &val, NULL))
+       if (timer_settime(timer->t_id, 0, &val, NULL))
                return 1;
        return 0;
 }
+void cancel_timer(struct ul_timer *timer)
+{
+       timer_delete(timer->t_id);
+}
+
+#else /* !HAVE_TIMER_CREATE */
+
+int setup_timer(struct ul_timer *timer,
+               struct itimerval *timeout,
+               void (*timeout_handler)(int, siginfo_t *, void *))
+{
+       struct sigaction sa;
+
+       memset(&sa, 0, sizeof sa);
+       memset(timer, 0, sizeof(*timer));
 
-void cancel_timer(timer_t *t_id)
+       sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
+       sa.sa_sigaction = timeout_handler;
+
+       if (sigaction(SIGALRM, &sa, &timer->old_sa))
+               return 1;
+       if (setitimer(ITIMER_REAL, timeout, &timer->old_timer) != 0)
+               return 1;
+       return 0;
+}
+
+void cancel_timer(struct ul_timer *timer)
 {
-       timer_delete(*t_id);
+       setitimer(ITIMER_REAL, &timer->old_timer, NULL);
+        sigaction(SIGALRM, &timer->old_sa, NULL);
+
 }
+#endif /* !HAVE_TIMER_CREATE */
index 8b83d91c045b6fb17ee105d2e87bfbec00773905..e0be809dde31e00535ab4e509d3e7fe38cc6e6ca 100644 (file)
@@ -298,7 +298,9 @@ static void timeout_handler(int sig __attribute__((__unused__)),
                            siginfo_t * info,
                            void *context __attribute__((__unused__)))
 {
+#ifdef HAVE_TIMER_CREATE
        if (info->si_code == SI_TIMER)
+#endif
                errx(EXIT_FAILURE, _("timed out"));
 }
 
@@ -327,18 +329,18 @@ static void server_loop(const char *socket_path, const char *pidfile_path,
        if (!uuidd_cxt->no_sock)        /* no_sock implies no_fork and no_pid */
 #endif
        {
-               static timer_t t_id;
+               struct ul_timer timer;
                struct itimerval timeout;
 
                memset(&timeout, 0, sizeof timeout);
                timeout.it_value.tv_sec = 30;
-               if (setup_timer(&t_id, &timeout, &timeout_handler))
+               if (setup_timer(&timer, &timeout, &timeout_handler))
                        err(EXIT_FAILURE, _("cannot set up timer"));
                if (pidfile_path)
                        fd_pidfile = create_pidfile(uuidd_cxt, pidfile_path);
                ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
                                  sizeof(reply_buf), 0, NULL);
-               cancel_timer(&t_id);
+               cancel_timer(&timer);
                if (ret > 0) {
                        if (!uuidd_cxt->quiet)
                                warnx(_("uuidd daemon is already running at pid %s"),
index ed25230b92913d8a7acaa3d12cfb46a369100796..57153c8d9af0a2d3884410aca5fe47955f696a03 100644 (file)
@@ -81,7 +81,9 @@ static void timeout_handler(int sig __attribute__((__unused__)),
                            siginfo_t *info,
                            void *context __attribute__((__unused__)))
 {
+#ifdef HAVE_TIMER_CREATE
        if (info->si_code == SI_TIMER)
+#endif
                timeout_expired = 1;
 }
 
@@ -124,7 +126,7 @@ static void __attribute__((__noreturn__)) run_program(char **cmd_argv)
 
 int main(int argc, char *argv[])
 {
-       static timer_t t_id;
+       struct ul_timer timer;
        struct itimerval timeout;
        int have_timeout = 0;
        int type = LOCK_EX;
@@ -268,7 +270,7 @@ int main(int argc, char *argv[])
                        have_timeout = 0;
                        block = LOCK_NB;
                } else
-                       if (setup_timer(&t_id, &timeout, &timeout_handler))
+                       if (setup_timer(&timer, &timeout, &timeout_handler))
                                err(EX_OSERR, _("cannot set up timer"));
        }
 
@@ -321,7 +323,7 @@ int main(int argc, char *argv[])
        }
 
        if (have_timeout)
-               cancel_timer(&t_id);
+               cancel_timer(&timer);
        if (verbose) {
                struct timeval delta;