3 #include <systemd/sd-daemon.h>
7 #include "../watchdog.h"
9 static timeout_t timer;
10 static struct timeval interval;
12 static uint64_t second_to_microsecond(time_t second) {
13 return second * 1000000;
16 static time_t microsecond_to_second(uint64_t micros) {
17 return (time_t)(micros / 1000000);
20 // Ignore errors from sd_notify() since there's nothing we can do if it breaks anyway.
21 // Also, there's this passage in `man sd_notify.3`:
22 // In order to support both service managers that implement this scheme and those
23 // which do not, it is generally recommended to ignore the return value of this call.
24 void watchdog_ping(void) {
25 sd_notify(false, "WATCHDOG=1");
28 static void watchdog_handler(void *data) {
31 timeout_set(&timer, &interval);
34 static bool watchdog_register(void) {
37 if(sd_watchdog_enabled(false, &timeout) <= 0 || !timeout) {
41 if(timeout < second_to_microsecond(2)) {
42 logger(DEBUG_ALWAYS, LOG_WARNING, "Consider using a higher watchdog timeout. Spurious failures may occur.");
45 // Send notifications twice per timeout period
48 interval.tv_sec = microsecond_to_second(timeout);
51 timeout -= second_to_microsecond(interval.tv_sec);
54 interval.tv_usec = (suseconds_t)timeout;
56 timeout_add(&timer, watchdog_handler, &timer, &interval);
62 void watchdog_start(void) {
63 sd_notify(false, "READY=1");
64 bool enabled = watchdog_register();
65 logger(DEBUG_ALWAYS, LOG_INFO, "Watchdog %s", enabled ? "started" : "is disabled");
68 void watchdog_stop(void) {
69 sd_notify(false, "STOPPING=1");