Signal handling improvements.
authorDavin McCall <davmac@davmac.org>
Thu, 8 Jun 2017 20:06:35 +0000 (21:06 +0100)
committerDavin McCall <davmac@davmac.org>
Thu, 8 Jun 2017 20:06:35 +0000 (21:06 +0100)
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
src/dinit.cc

index ed10a5bbd96d8eccdd474a021e34290ed11a7530..57fb4e5509dce30cd739c02e21873db7687e0917 100644 (file)
@@ -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.
index 450a2fc30c7cf26e1623a7c941343e33f933e64c..282d4b157750a2f1bb70047ab8a0b94914487dba 100644 (file)
@@ -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;
 }