From 6df5acf970852a94b254800dc69569bd1f4c9ae8 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 24 Oct 2018 12:28:13 +0200 Subject: lib/timer: add fallback if timer_create() not available * 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 --- configure.ac | 4 ++++ include/timer.h | 15 +++++++++++++-- lib/timer.c | 40 +++++++++++++++++++++++++++++++++++----- misc-utils/uuidd.c | 8 +++++--- sys-utils/flock.c | 8 +++++--- 5 files changed, 62 insertions(+), 13 deletions(-) diff --git a/configure.ac b/configure.ac index 21b04f581..e6cfd4605 100644 --- a/configure.ac +++ b/configure.ac @@ -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" diff --git a/include/timer.h b/include/timer.h index aa9f9c018..70da1ba9e 100644 --- a/include/timer.h +++ b/include/timer.h @@ -4,8 +4,19 @@ #include #include -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 */ diff --git a/lib/timer.c b/lib/timer.c index 210c726cb..c1ea54eb8 100644 --- a/lib/timer.c +++ b/lib/timer.c @@ -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 */ diff --git a/misc-utils/uuidd.c b/misc-utils/uuidd.c index 8b83d91c0..e0be809dd 100644 --- a/misc-utils/uuidd.c +++ b/misc-utils/uuidd.c @@ -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"), diff --git a/sys-utils/flock.c b/sys-utils/flock.c index ed25230b9..57153c8d9 100644 --- a/sys-utils/flock.c +++ b/sys-utils/flock.c @@ -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; -- cgit v1.2.3-55-g7522