summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Zak2018-10-24 12:28:13 +0200
committerKarel Zak2018-12-03 11:23:33 +0100
commit6df5acf970852a94b254800dc69569bd1f4c9ae8 (patch)
tree18751217f934f0dd328edd69fe4da5b6bfb0428c /lib
parentbuild-sys: make sure HAVE_TIMER_CREATE defined (diff)
downloadkernel-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.c40
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 */