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>
This commit is contained in:
parent
9a558f9cf6
commit
6df5acf970
|
@ -558,6 +558,10 @@ AC_CHECK_FUNCS([timer_create],
|
||||||
|
|
||||||
AC_SUBST([REALTIME_LIBS])
|
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], [
|
AC_CHECK_LIB([rtas], [rtas_get_sysparm], [
|
||||||
RTAS_LIBS="-lrtas"
|
RTAS_LIBS="-lrtas"
|
||||||
|
|
|
@ -4,8 +4,19 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/time.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 *));
|
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 */
|
#endif /* UTIL_LINUX_TIMER_H */
|
||||||
|
|
40
lib/timer.c
40
lib/timer.c
|
@ -27,7 +27,9 @@
|
||||||
* The applications need to ensure that they can tolerate multiple signal
|
* The applications need to ensure that they can tolerate multiple signal
|
||||||
* deliveries.
|
* 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 *))
|
void (*timeout_handler)(int, siginfo_t *, void *))
|
||||||
{
|
{
|
||||||
time_t sec = timeout->it_value.tv_sec;
|
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))
|
if (sigaction(SIGALRM, &sig_a, NULL))
|
||||||
return 1;
|
return 1;
|
||||||
if (timer_create(CLOCK_MONOTONIC, &sig_e, t_id))
|
if (timer_create(CLOCK_MONOTONIC, &sig_e, &timer->t_id))
|
||||||
return 1;
|
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));
|
||||||
|
|
||||||
|
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 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancel_timer(timer_t *t_id)
|
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 */
|
||||||
|
|
|
@ -298,7 +298,9 @@ static void timeout_handler(int sig __attribute__((__unused__)),
|
||||||
siginfo_t * info,
|
siginfo_t * info,
|
||||||
void *context __attribute__((__unused__)))
|
void *context __attribute__((__unused__)))
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_TIMER_CREATE
|
||||||
if (info->si_code == SI_TIMER)
|
if (info->si_code == SI_TIMER)
|
||||||
|
#endif
|
||||||
errx(EXIT_FAILURE, _("timed out"));
|
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 */
|
if (!uuidd_cxt->no_sock) /* no_sock implies no_fork and no_pid */
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static timer_t t_id;
|
struct ul_timer timer;
|
||||||
struct itimerval timeout;
|
struct itimerval timeout;
|
||||||
|
|
||||||
memset(&timeout, 0, sizeof timeout);
|
memset(&timeout, 0, sizeof timeout);
|
||||||
timeout.it_value.tv_sec = 30;
|
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"));
|
err(EXIT_FAILURE, _("cannot set up timer"));
|
||||||
if (pidfile_path)
|
if (pidfile_path)
|
||||||
fd_pidfile = create_pidfile(uuidd_cxt, pidfile_path);
|
fd_pidfile = create_pidfile(uuidd_cxt, pidfile_path);
|
||||||
ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
|
ret = call_daemon(socket_path, UUIDD_OP_GETPID, reply_buf,
|
||||||
sizeof(reply_buf), 0, NULL);
|
sizeof(reply_buf), 0, NULL);
|
||||||
cancel_timer(&t_id);
|
cancel_timer(&timer);
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
if (!uuidd_cxt->quiet)
|
if (!uuidd_cxt->quiet)
|
||||||
warnx(_("uuidd daemon is already running at pid %s"),
|
warnx(_("uuidd daemon is already running at pid %s"),
|
||||||
|
|
|
@ -81,7 +81,9 @@ static void timeout_handler(int sig __attribute__((__unused__)),
|
||||||
siginfo_t *info,
|
siginfo_t *info,
|
||||||
void *context __attribute__((__unused__)))
|
void *context __attribute__((__unused__)))
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_TIMER_CREATE
|
||||||
if (info->si_code == SI_TIMER)
|
if (info->si_code == SI_TIMER)
|
||||||
|
#endif
|
||||||
timeout_expired = 1;
|
timeout_expired = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +126,7 @@ static void __attribute__((__noreturn__)) run_program(char **cmd_argv)
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static timer_t t_id;
|
struct ul_timer timer;
|
||||||
struct itimerval timeout;
|
struct itimerval timeout;
|
||||||
int have_timeout = 0;
|
int have_timeout = 0;
|
||||||
int type = LOCK_EX;
|
int type = LOCK_EX;
|
||||||
|
@ -268,7 +270,7 @@ int main(int argc, char *argv[])
|
||||||
have_timeout = 0;
|
have_timeout = 0;
|
||||||
block = LOCK_NB;
|
block = LOCK_NB;
|
||||||
} else
|
} else
|
||||||
if (setup_timer(&t_id, &timeout, &timeout_handler))
|
if (setup_timer(&timer, &timeout, &timeout_handler))
|
||||||
err(EX_OSERR, _("cannot set up timer"));
|
err(EX_OSERR, _("cannot set up timer"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +323,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_timeout)
|
if (have_timeout)
|
||||||
cancel_timer(&t_id);
|
cancel_timer(&timer);
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
struct timeval delta;
|
struct timeval delta;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue