diff --git a/api.c b/api.c index 129e50db..2f16ad51 100644 --- a/api.c +++ b/api.c @@ -323,6 +323,19 @@ static void cb(uev_t *w, void *UNUSED(arg), int UNUSED(events)) _d("Client failed reading ACK"); goto leave; + case INIT_CMD_WDOG_HELLO: + if (rq.runlevel <= 0) { + result = 1; + break; + } + + if (wdogpid > 0 && wdogpid != rq.runlevel) { + kill(wdogpid, SIGTERM); + do_sleep(1); + } + wdogpid = rq.runlevel; + break; + default: _d("Unsupported cmd: %d", rq.cmd); break; diff --git a/finit.c b/finit.c index c97d2009..1facf826 100644 --- a/finit.c +++ b/finit.c @@ -50,6 +50,7 @@ int debug = 0; int quiet = QUIET_MODE; /* Delayed disable of silent mode. */ int silent = SILENT_MODE; /* Completely silent, including boot */ +int wdogpid = 0; /* No watchdog by default */ int runlevel = 0; /* Bootstrap 'S' */ int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */ int prevlevel = -1; diff --git a/finit.h b/finit.h index 71b8fa23..285da21c 100644 --- a/finit.h +++ b/finit.h @@ -67,6 +67,7 @@ #define INIT_CMD_QUERY_INETD 14 #define INIT_CMD_EMIT 15 #define INIT_CMD_GET_RUNLEVEL 16 +#define INIT_CMD_WDOG_HELLO 128 /* Watchdog register and hello */ #define INIT_CMD_NACK 254 #define INIT_CMD_ACK 255 @@ -81,6 +82,7 @@ struct init_request { extern int debug; extern int quiet; extern int silent; +extern int wdogpid; extern int runlevel; extern int cfglevel; extern int prevlevel; diff --git a/sig.c b/sig.c index dd0f9aa7..e552c71f 100644 --- a/sig.c +++ b/sig.c @@ -194,6 +194,15 @@ void do_shutdown(shutop_t op) /* Call mdadm to mark any RAID array(s) as clean before halting. */ mdadm_wait(); + /* Wait here until the WDT reboots, or timeout */ + if (wdogpid) { + int timeout = 10; + + print(kill(wdogpid, SIGPWR) == 1, "Pending watchdog reboot"); + while (timeout--) + do_sleep(1); + } + _d("%s", op == SHUT_REBOOT ? "Rebooting" : "Halting"); if (op == SHUT_REBOOT) reboot(RB_AUTOBOOT);