diff --git a/include/haproxy/clock.h b/include/haproxy/clock.h index 77fd7ec78..2cee76da4 100644 --- a/include/haproxy/clock.h +++ b/include/haproxy/clock.h @@ -39,6 +39,7 @@ void clock_set_local_source(void); void clock_update_date(int max_wait, int interrupted); void clock_init_process_date(void); void clock_init_thread_date(void); +int clock_setup_signal_timer(void *timer, int sig, int val); char *timeofday_as_iso_us(int pad); uint clock_report_idle(void); void clock_leaving_poll(int timeout, int interrupted); diff --git a/src/clock.c b/src/clock.c index 5a3447f2b..517f0a3a5 100644 --- a/src/clock.c +++ b/src/clock.c @@ -11,6 +11,7 @@ */ #include +#include #include #ifdef USE_THREAD @@ -20,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +47,7 @@ static THREAD_LOCAL char iso_time_str[34]; /* ISO time representation of uint64_t now_mono_time(void) { uint64_t ret = 0; -#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) +#if defined(_POSIX_TIMERS) && defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0) && defined(_POSIX_MONOTONIC_CLOCK) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); ret = ts.tv_sec * 1000000000ULL + ts.tv_nsec; @@ -89,6 +91,37 @@ void clock_set_local_source(void) #endif } +/* registers a timer of type timer_t delivering signal with value + * . It tries on the current thread's clock ID first and falls back to + * CLOCK_REALTIME. Returns non-zero on success, 1 on failure. + */ +int clock_setup_signal_timer(void *tmr, int sig, int val) +{ + int ret = 0; + +#if defined(USE_RT) && (_POSIX_TIMERS > 0) && defined(_POSIX_THREAD_CPUTIME) + struct sigevent sev = { }; + timer_t *timer = tmr; + sigset_t set; + + /* unblock the WDTSIG signal we intend to use */ + sigemptyset(&set); + sigaddset(&set, WDTSIG); + ha_sigmask(SIG_UNBLOCK, &set, NULL); + + /* this timer will signal WDTSIG when it fires, with tid in the si_int + * field (important since any thread will receive the signal). + */ + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = sig; + sev.sigev_value.sival_int = val; + if (timer_create(ti->clock_id, &sev, timer) != -1 || + timer_create(CLOCK_REALTIME, &sev, timer) != -1) + ret = 1; +#endif + return ret; +} + /* clock_update_date: sets to system time, and sets to something as * close as possible to real time, following a monotonic function. The main * principle consists in detecting backwards and forwards time jumps and adjust diff --git a/src/wdt.c b/src/wdt.c index 066f109ab..a893b5d89 100644 --- a/src/wdt.c +++ b/src/wdt.c @@ -127,22 +127,7 @@ void wdt_handler(int sig, siginfo_t *si, void *arg) int init_wdt_per_thread() { - struct sigevent sev = { }; - sigset_t set; - - /* unblock the WDTSIG signal we intend to use */ - sigemptyset(&set); - sigaddset(&set, WDTSIG); - ha_sigmask(SIG_UNBLOCK, &set, NULL); - - /* this timer will signal WDTSIG when it fires, with tid in the si_int - * field (important since any thread will receive the signal). - */ - sev.sigev_notify = SIGEV_SIGNAL; - sev.sigev_signo = WDTSIG; - sev.sigev_value.sival_int = tid; - if (timer_create(ti->clock_id, &sev, &ti->wd_timer) == -1 && - timer_create(CLOCK_REALTIME, &sev, &ti->wd_timer) == -1) + if (!clock_setup_signal_timer(&ti->wd_timer, WDTSIG, tid)) goto fail1; if (!wdt_ping(tid))