diff options
-rw-r--r-- | toys/pending/watchdog.c | 120 |
1 files changed, 20 insertions, 100 deletions
diff --git a/toys/pending/watchdog.c b/toys/pending/watchdog.c index 0813fe69..d1279bd4 100644 --- a/toys/pending/watchdog.c +++ b/toys/pending/watchdog.c @@ -1,128 +1,48 @@ /* watchdog - start a watchdog timer with configurable kick frequencies + * + * Copyright 2019 Chris Sarra <chrissarra@google.com> + * + * See kernel.org/doc/Documentation/watchdog/watchdog-api.txt - Author: Chris Sarra, chrissarra@google.com - Date: 25 July 2019 - Ref: kernel.org/doc/Documentation/watchdog/watchdog-api.txt - -USE_WATCHDOG(NEWTOY(watchdog, "Ft#T#", TOYFLAG_NEEDROOT|TOYFLAG_BIN)) +USE_WATCHDOG(NEWTOY(watchdog, "<1>1Ft#=4<1T#=60<1", TOYFLAG_NEEDROOT|TOYFLAG_BIN)) config WATCHDOG bool "watchdog" - default y + default n help usage: watchdog [-F] [-t SW_TIMER_S] [-T HW_TIMER_S] DEV Start the watchdog timer at DEV with optional timeout parameters. - -F run in the foreground (do not daemonize) - -t software timer (in seconds) - -T hardware timer (in seconds) + + -F run in the foreground (do not daemonize) + -t software timer (in seconds) + -T hardware timer (in seconds) */ #define FOR_watchdog #include "toys.h" #include "linux/watchdog.h" -// Make sure no DEBUG variable is set; change this if you need debug prints! -#undef WATCHDOG_DEBUG - -// Default timeout values in seconds. -#define WATCHDOG_SW_TIMER_S_DEFAULT (4) -#define WATCHDOG_HW_TIMER_S_DEFAULT (60) - GLOBALS( - long hw_timer_s; - long sw_timer_s; + long T, t; + int fd; ) -static int intercept_signals(void (*fn)(int)) { - int rc = 0; - struct sigaction sigact; - memset(&sigact, 0, sizeof(sigact)); - sigact.sa_handler = fn; - - rc = sigaction(SIGTERM, &sigact, NULL); -#if defined(WATCHDOG_DEBUG) - if ( rc ) { - printf("failed to create new sigaction for SIGTERM: %d\n", rc); - } -#endif - return rc; -} - -void safe_shutdown(int __attribute__((unused))ignored) { +void safe_shutdown(int ignored) { write(TT.fd, "V", 1); close(TT.fd); - TT.fd = -1; error_exit("safely exited watchdog."); } -void watchdog_main(void) { - int rc = 0; - long hw_timer_sec = 0; - char *watchdog_dev = NULL; - - if ( toys.optc > 0 ) { - watchdog_dev = toys.optargs[0]; -#if defined(WATCHDOG_DEBUG) - printf("using dev @ '%s'\n", watchdog_dev); -#endif - } else { - error_exit("watchdog dev required"); - } - - // Set default values for timeouts if no flags - if (!(toys.optflags & FLAG_t)) { - TT.sw_timer_s = WATCHDOG_SW_TIMER_S_DEFAULT; -#if defined(WATCHDOG_DEBUG) - printf("using default sw_timer_s.\n"); -#endif - } - - if (!(toys.optflags & FLAG_T)) { - TT.hw_timer_s = WATCHDOG_HW_TIMER_S_DEFAULT; -#if defined(WATCHDOG_DEBUG) - printf("using default hw_timer_s.\n"); -#endif - } - -#if defined(WATCHDOG_DEBUG) - printf("hw timer: %ld seconds\n", TT.hw_timer_s); - printf("sw timer: %ld seconds\n", TT.sw_timer_s); -#endif - - if (!(toys.optflags & FLAG_F)) { -#if defined(WATCHDOG_DEBUG) - printf("daemonizing. so long, foreground!\n"); -#endif - // Attempt to daemonize - rc = daemon(1, 1); - if ( rc ) { - perror_exit("failed to daemonize: %d", rc); - } - } - - // Intercept terminating signals so we can call our shutdown routine first. - if ( intercept_signals(safe_shutdown) ) { - perror_exit("failed to intercept desired signals: %d", rc); - } -#if defined(WATCHDOG_DEBUG) - printf("Successfully intercepted signals.\n"); -#endif - - TT.fd = open(watchdog_dev, O_WRONLY); - if ( TT.fd == -1 ) { - perror_exit("failed to open '%s'", watchdog_dev); - } - -#if defined(WDIOC_SETTIMEOUT) - // SETTIMEOUT takes time value in seconds: s = ms / (1000 ms/s) - hw_timer_sec = TT.hw_timer_s; - xioctl(TT.fd, WDIOC_SETTIMEOUT, (void *)&hw_timer_sec); -#endif // WDIOC_SETTIMEOUT +void watchdog_main(void) +{ + if (!FLAG(F) && daemon(1, 1)) perror_exit("failed to daemonize"); + xsignal(SIGTERM, safe_shutdown); + xioctl(TT.fd = xopen(*toys.optargs, O_WRONLY), WDIOC_SETTIMEOUT, &TT.T); // Now that we've got the watchdog device open, kick it periodically. - while (1) { + for (;;) { write(TT.fd, "\0", 1); - usleep(TT.sw_timer_s * 1000 * 1000); + sleep(TT.t); } } |