X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fprocd.git;a=blobdiff_plain;f=watchdog.c;h=ec10ba6188ca39138a46b805becc91a18ba2c059;hp=399f6af7f1a9cff0be7d91dcdcb9e1d63e1b4ea7;hb=67eb7e68165bfa29ab57eb82f3e40eca17662365;hpb=13259259bc53657617844660f2664f4b4fb4ac02 diff --git a/watchdog.c b/watchdog.c index 399f6af..ec10ba6 100644 --- a/watchdog.c +++ b/watchdog.c @@ -31,21 +31,81 @@ static struct uloop_timeout wdt_timeout; static int wdt_fd = -1; static int wdt_frequency = 5; +static bool wdt_magicclose = false; -static void watchdog_timeout_cb(struct uloop_timeout *t) +void watchdog_ping(void) { DEBUG(4, "Ping\n"); - if (write(wdt_fd, "X", 1) < 0) - ERROR("WDT failed to write: %s\n", strerror(errno)); + if (wdt_fd >= 0 && write(wdt_fd, "X", 1) < 0) + ERROR("WDT failed to write: %m\n"); +} + +static void watchdog_timeout_cb(struct uloop_timeout *t) +{ + watchdog_ping(); uloop_timeout_set(t, wdt_frequency * 1000); } +static int watchdog_open(bool cloexec) +{ + char *env = getenv("WDTFD"); + + if (wdt_fd >= 0) + return wdt_fd; + + if (env) { + DEBUG(2, "Watchdog handover: fd=%s\n", env); + wdt_fd = atoi(env); + unsetenv("WDTFD"); + } else { + wdt_fd = open(WDT_PATH, O_WRONLY); + } + + if (wdt_fd < 0) + return wdt_fd; + + if (cloexec) + fcntl(wdt_fd, F_SETFD, fcntl(wdt_fd, F_GETFD) | FD_CLOEXEC); + + return wdt_fd; +} + +static void watchdog_close(void) +{ + if (wdt_fd < 0) + return; + + if (write(wdt_fd, "V", 1) < 0) + ERROR("WDT failed to write release: %m\n"); + + if (close(wdt_fd) == -1) + ERROR("WDT failed to close watchdog: %m\n"); + + wdt_fd = -1; +} + +void watchdog_set_magicclose(bool val) +{ + wdt_magicclose = val; +} + +bool watchdog_get_magicclose(void) +{ + return wdt_magicclose; +} + void watchdog_set_stopped(bool val) { - if (val) + if (val) { uloop_timeout_cancel(&wdt_timeout); - else + + if (wdt_magicclose) + watchdog_close(); + } + else { + watchdog_open(true); watchdog_timeout_cb(&wdt_timeout); + } } bool watchdog_get_stopped(void) @@ -93,26 +153,11 @@ char* watchdog_fd(void) void watchdog_init(int preinit) { - char *env = getenv("WDTFD"); - - if (wdt_fd >= 0) - return; - wdt_timeout.cb = watchdog_timeout_cb; - if (env) { - DEBUG(2, "Watchdog handover: fd=%s\n", env); - wdt_fd = atoi(env); - unsetenv("WDTFD"); - } else { - wdt_fd = open("/dev/watchdog", O_WRONLY); - } - if (wdt_fd < 0) + if (watchdog_open(!preinit) < 0) return; - if (!preinit) - fcntl(wdt_fd, F_SETFD, fcntl(wdt_fd, F_GETFD) | FD_CLOEXEC); - LOG("- watchdog -\n"); watchdog_timeout(30); watchdog_timeout_cb(&wdt_timeout); @@ -121,10 +166,15 @@ void watchdog_init(int preinit) } -void watchdog_no_cloexec(void) +void watchdog_set_cloexec(bool val) { if (wdt_fd < 0) return; - fcntl(wdt_fd, F_SETFD, fcntl(wdt_fd, F_GETFD) & ~FD_CLOEXEC); + int flags = fcntl(wdt_fd, F_GETFD); + if (val) + flags |= FD_CLOEXEC; + else + flags &= ~FD_CLOEXEC; + fcntl(wdt_fd, F_SETFD, flags); }