From f27716635416348b9f4b2f6018d40ecd3f6c111a Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Fri, 17 May 2013 15:13:43 +0200 Subject: [PATCH] sig.c: Use watchdogd to reboot system This patch reorders the shutdown/reboot handler slightly and fixes a bug in sleep(). It seems the sleep() syscall was interrupted by receiving lots of SIGCHLD. Unsurprisingly since we just sent all processes SIGTERM, but unfortunate since that was too short time to deliver SIGTERM to watchdogd. We now call sleep() again, as long as it returns a non-zero value, until at most two (2) seconds have passed. During this time we basically pend for watchdogd to do its job and let the WDT reboot the system. If the two second timeout passes we send SIGKILL and forcibly reboot(RB_AUTOBOOT) the system. Signed-off-by: Joachim Nilsson --- sig.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/sig.c b/sig.c index 7362f058..8548df7d 100644 --- a/sig.c +++ b/sig.c @@ -49,6 +49,12 @@ static int stopped = 0; +/* Signal safe sleep ... we get a lot of SIGCHLD at reboot */ +void do_sleep(unsigned int sec) +{ + while ((sec = sleep(sec))) + ; +} void do_shutdown (int sig) { @@ -57,12 +63,15 @@ void do_shutdown (int sig) if (sdown) run_interactive(sdown, "Calling shutdown hook: %s", sdown); + /* Call all shutdown hooks before rebooting... */ + plugin_run_hooks(HOOK_SHUTDOWN); + + /* Here is where we signal watchdogd to do a forced reset for us */ _d("Sending SIGTERM to all processes."); kill(-1, SIGTERM); - sleep(1); - /* Call all shutdown hooks, this is the last call before rebooting... */ - plugin_run_hooks(HOOK_SHUTDOWN); + /* Wait for WDT to timeout, should be no more than ~1 sec. */ + do_sleep(2); _d("Sending SIGKILL to remaining processes."); kill(-1, SIGKILL);