From a503a675759210beb1d8a4f2a07af4bf94d8e2c9 Mon Sep 17 00:00:00 2001 From: Davin McCall Date: Thu, 8 Jun 2017 21:06:35 +0100 Subject: [PATCH] Signal handling improvements. Don't handle SIGQUIT in user mode. Also, when receiving SIGINT in user mode, terminate via SIGINT so that the correct exit status is returned. --- doc/manpages/dinit.1 | 9 +++++++++ src/dinit.cc | 33 +++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/doc/manpages/dinit.1 b/doc/manpages/dinit.1 index ed10a5b..57fb4e5 100644 --- a/doc/manpages/dinit.1 +++ b/doc/manpages/dinit.1 @@ -298,5 +298,14 @@ depends-on = device-node-daemon More examples are provided with the Dinit distribution. .\" +.SH SIGNALS +.LP +When run as a system process, SIGINT stops all services and performs a reboot (on Linux, this signal can be +generated using the control-alt-delete key combination); SIGTERM stops services and halts the system; and +SIGQUIT performs an immediate shutdown with no service rollback. +LP +When run as a user process, SIGINT and SIGTERM both stop services and exit Dinit; SIGQUIT exits Dinit +immediately. +.\" .SH AUTHOR Dinit, and this manual, were written by Davin McCall. diff --git a/src/dinit.cc b/src/dinit.cc index 450a2fc..282d4b1 100644 --- a/src/dinit.cc +++ b/src/dinit.cc @@ -276,29 +276,26 @@ static int dinit_main(int argc, char **argv) } // Set up signal handlers + CallbackSignalHandler sigterm_watcher {sigterm_cb}; CallbackSignalHandler sigint_watcher; - if (am_system_init) { - sigint_watcher.setCbFunc(sigint_reboot_cb); - } - else { - sigint_watcher.setCbFunc(sigterm_cb); - } - CallbackSignalHandler sigquit_watcher; + if (am_system_init) { - // PID 1: SIGQUIT exec's shutdown + sigint_watcher.setCbFunc(sigint_reboot_cb); sigquit_watcher.setCbFunc(sigquit_cb); } else { - // Otherwise: SIGQUIT terminates dinit - sigquit_watcher.setCbFunc(sigterm_cb); + sigint_watcher.setCbFunc(sigterm_cb); } - - CallbackSignalHandler sigterm_watcher {sigterm_cb}; - + sigint_watcher.add_watch(eventLoop, SIGINT); - sigquit_watcher.add_watch(eventLoop, SIGQUIT); sigterm_watcher.add_watch(eventLoop, SIGTERM); + + if (am_system_init) { + // PID 1: SIGQUIT exec's shutdown + sigquit_watcher.add_watch(eventLoop, SIGQUIT); + // As a user process, we instead just let SIGQUIT perform the default action. + } // Try to open control socket (may fail due to readonly filesystem) open_control_socket(false); @@ -407,6 +404,14 @@ static int dinit_main(int argc, char **argv) eventLoop.run(); } } + else if (shutdown_type == ShutdownType::REBOOT) { + // Non-system-process. If we got SIGINT, let's die due to it: + sigset_t sigwait_set; + sigemptyset(&sigwait_set); + sigaddset(&sigwait_set, SIGINT); + raise(SIGINT); + sigprocmask(SIG_UNBLOCK, &sigwait_set, NULL); + } return 0; } -- 2.25.1