diff --git a/src/api.c b/src/api.c index c6ac7254..bd6b5a34 100644 --- a/src/api.c +++ b/src/api.c @@ -44,6 +44,7 @@ #include "service.h" #include "util.h" +extern svc_t *wdog; static uev_t api_watcher; static int call(int (*action)(svc_t *), char *buf, size_t len) @@ -340,13 +341,23 @@ static void api_cb(uev_t *w, void *arg, int events) break; } - if (wdogpid > 0 && wdogpid != rq.runlevel) { - _d("Sending SIGTERM to %d", wdogpid); - kill(wdogpid, SIGTERM); - do_sleep(1); + _e("Request to hand-over wdog ... to PID %d", rq.runlevel); + svc = svc_find_by_pid(rq.runlevel); + if (!svc) { + logit(LOG_ERR, "Cannot find PID %d, not registered.", rq.runlevel); + break; } - _d("wdog was %d, now %d is in charge", wdogpid, rq.runlevel); - wdogpid = rq.runlevel; + + /* Disable and allow Finit to collect bundled watchdog */ + if (wdog) { + logit(LOG_NOTICE, "Stopping and removing %s (PID:%d)", wdog->cmd, wdog->pid); + stop(wdog); + if (wdog->protected) { + wdog->protected = 0; + wdog->runlevels = 0; + } + } + wdog = svc; break; case INIT_CMD_SVC_ITER: diff --git a/src/finit.c b/src/finit.c index 5ab8891f..2d02b369 100644 --- a/src/finit.c +++ b/src/finit.c @@ -48,7 +48,6 @@ #include "util.h" #include "utmp-api.h" -int wdogpid = 0; /* No watchdog by default */ int runlevel = 0; /* Bootstrap 'S' */ int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */ int prevlevel = -1; @@ -62,6 +61,7 @@ char *rcsd = FINIT_RCSD; char *runparts = NULL; uev_ctx_t *ctx = NULL; /* Main loop context */ +svc_t *wdog = NULL; /* No watchdog by default */ /* * Show user configured banner before service bootstrap progress @@ -215,16 +215,19 @@ static void finalize(void) { svc_t *svc; + /* + * Track bundled watchdogd in case a better one turns up + */ + svc = svc_find(FINIT_LIBPATH_ "/watchdogd", 1); + if (svc) + wdog = svc; + /* * Run startup scripts in the runparts directory, if any. */ if (runparts && fisdir(runparts) && !rescue) run_parts(runparts, NULL); - svc = svc_find(FINIT_LIBPATH_ "watchdogd", 1); - if (svc && !wdogpid) - wdogpid = svc->pid; - /* * Start all tasks/services in the configured runlevel */ diff --git a/src/finit.h b/src/finit.h index 95b02493..57b34c4b 100644 --- a/src/finit.h +++ b/src/finit.h @@ -92,7 +92,6 @@ struct init_request { char data[368]; }; -extern int wdogpid; extern int runlevel; extern int cfglevel; extern int prevlevel; diff --git a/src/sig.c b/src/sig.c index d0d279e8..96a67ba5 100644 --- a/src/sig.c +++ b/src/sig.c @@ -83,6 +83,8 @@ #include "util.h" #include "utmp-api.h" +extern svc_t *wdog; + /* * Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT", * "=POWERDOWN", or "" to cancel shutdown, before requesting change to @@ -185,8 +187,8 @@ void do_shutdown(shutop_t op) return; } - if (wdogpid) { - print(kill(wdogpid, SIGPWR) == 1, "Advising watchdog, system going down"); + if (wdog) { + print(kill(wdog->pid, SIGPWR) == 1, "Advising watchdog, system going down"); do_sleep(2); } @@ -208,11 +210,11 @@ void do_shutdown(shutop_t op) /* Reboot via watchdog or kernel, or shutdown? */ if (op == SHUT_REBOOT) { - if (wdogpid) { + if (wdog) { int timeout = 10; /* Wait here until the WDT reboots, or timeout with fallback */ - print(kill(wdogpid, SIGTERM) == 1, "Pending watchdog reboot"); + print(kill(wdog->pid, SIGTERM) == 1, "Pending watchdog reboot"); while (timeout--) do_sleep(1); }