diff options
author | Karel Zak | 2018-10-24 12:28:13 +0200 |
---|---|---|
committer | Karel Zak | 2018-12-03 11:23:33 +0100 |
commit | 6df5acf970852a94b254800dc69569bd1f4c9ae8 (patch) | |
tree | 18751217f934f0dd328edd69fe4da5b6bfb0428c /lib | |
parent | build-sys: make sure HAVE_TIMER_CREATE defined (diff) | |
download | kernel-qcow2-util-linux-6df5acf970852a94b254800dc69569bd1f4c9ae8.tar.gz kernel-qcow2-util-linux-6df5acf970852a94b254800dc69569bd1f4c9ae8.tar.xz kernel-qcow2-util-linux-6df5acf970852a94b254800dc69569bd1f4c9ae8.zip |
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 <kzak@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/timer.c | 40 |
1 files changed, 35 insertions, 5 deletions
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 */ |