X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=miscutils%2Fwatchdog.c;h=07ae64e52afbae01f090a6e7c01d6b34018b84bb;hb=179e88bec91cfe58096900dc5509a080ff37b083;hp=75a399f24ed64b0414057466aa6542aa284f4d6a;hpb=93d0776a96919a94fca51fe2cfd9530d8c9dcbb9;p=oweals%2Fbusybox.git diff --git a/miscutils/watchdog.c b/miscutils/watchdog.c index 75a399f24..07ae64e52 100644 --- a/miscutils/watchdog.c +++ b/miscutils/watchdog.c @@ -6,10 +6,36 @@ * Copyright (C) 2006 Bernhard Reutner-Fischer * Copyright (C) 2008 Darius Augulis * - * Licensed under the GPL v2 or later, see the file LICENSE in this tarball. + * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//config:config WATCHDOG +//config: bool "watchdog" +//config: default y +//config: select PLATFORM_LINUX +//config: help +//config: The watchdog utility is used with hardware or software watchdog +//config: device drivers. It opens the specified watchdog device special file +//config: and periodically writes a magic character to the device. If the +//config: watchdog applet ever fails to write the magic character within a +//config: certain amount of time, the watchdog device assumes the system has +//config: hung, and will cause the hardware to reboot. + +//applet:IF_WATCHDOG(APPLET(watchdog, BB_DIR_SBIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_WATCHDOG) += watchdog.o + +//usage:#define watchdog_trivial_usage +//usage: "[-t N[ms]] [-T N[ms]] [-F] DEV" +//usage:#define watchdog_full_usage "\n\n" +//usage: "Periodically write to watchdog device DEV\n" +//usage: "\n -T N Reboot after N seconds if not reset (default 60)" +//usage: "\n -t N Reset every N seconds (default 30)" +//usage: "\n -F Run in foreground" +//usage: "\n" +//usage: "\nUse 500ms to specify period in milliseconds" #include "libbb.h" +#include "linux/types.h" /* for __u32 */ #include "linux/watchdog.h" #define OPT_FOREGROUND (1 << 0) @@ -20,10 +46,11 @@ static void watchdog_shutdown(int sig UNUSED_PARAM) { static const char V = 'V'; - write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ + remove_pidfile(CONFIG_PID_FILE_PATH "/watchdog.pid"); + write(3, &V, 1); /* Magic, see watchdog-api.txt in kernel */ if (ENABLE_FEATURE_CLEAN_UP) close(3); - exit(EXIT_SUCCESS); + _exit(EXIT_SUCCESS); } int watchdog_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -32,7 +59,7 @@ int watchdog_main(int argc, char **argv) static const struct suffix_mult suffixes[] = { { "ms", 1 }, { "", 1000 }, - { } + { "", 0 } }; unsigned opts; @@ -44,6 +71,15 @@ int watchdog_main(int argc, char **argv) opt_complementary = "=1"; /* must have exactly 1 argument */ opts = getopt32(argv, "Ft:T:", &st_arg, &ht_arg); + /* We need to daemonize *before* opening the watchdog as many drivers + * will only allow one process at a time to do so. Since daemonizing + * is not perfect (child may run before parent finishes exiting), we + * can't rely on parent exiting before us (let alone *cleanly* releasing + * the watchdog fd -- something else that may not even be allowed). + */ + if (!(opts & OPT_FOREGROUND)) + bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); + if (opts & OPT_HTIMER) htimer_duration = xatou_sfx(ht_arg, suffixes); stimer_duration = htimer_duration / 2; @@ -57,21 +93,30 @@ int watchdog_main(int argc, char **argv) /* WDIOC_SETTIMEOUT takes seconds, not milliseconds */ htimer_duration = htimer_duration / 1000; +#ifndef WDIOC_SETTIMEOUT +# error WDIOC_SETTIMEOUT is not defined, cannot compile watchdog applet +#else +# if defined WDIOC_SETOPTIONS && defined WDIOS_ENABLECARD + { + static const int enable = WDIOS_ENABLECARD; + ioctl_or_warn(3, WDIOC_SETOPTIONS, (void*) &enable); + } +# endif ioctl_or_warn(3, WDIOC_SETTIMEOUT, &htimer_duration); +#endif + #if 0 ioctl_or_warn(3, WDIOC_GETTIMEOUT, &htimer_duration); - printf("watchdog: SW timer is %dms, HW timer is %dms\n", + printf("watchdog: SW timer is %dms, HW timer is %ds\n", stimer_duration, htimer_duration * 1000); #endif - if (!(opts & OPT_FOREGROUND)) { - bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv); - } + write_pidfile(CONFIG_PID_FILE_PATH "/watchdog.pid"); while (1) { /* - * Make sure we clear the counter before sleeping, as the counter value - * is undefined at this point -- PFM + * Make sure we clear the counter before sleeping, + * as the counter value is undefined at this point -- PFM */ write(3, "", 1); /* write zero byte */ usleep(stimer_duration * 1000L);