Do not try to manage system (shutdown, reboot) if not running as PID 1.
authorDavin McCall <davmac@davmac.org>
Sun, 21 Oct 2018 20:58:10 +0000 (21:58 +0100)
committerDavin McCall <davmac@davmac.org>
Sun, 21 Oct 2018 20:58:10 +0000 (21:58 +0100)
If not PID 1, assume system management is being taken care of by a
separate primary init.

doc/manpages/dinit.8
src/dinit.cc

index ee3c932a0cf95a7927efbdd672f60371fc67b311..db5b84809703f5b7927d3d8a34d442dc184f552d 100644 (file)
@@ -83,6 +83,19 @@ to use other character sets may see odd behaviour if the input character set doe
 not match the output character set, or if either input or output character sets
 are not a superset of the execution character set.
 .\"
+.SS RUNNING AS SYSTEM MANAGER / PRIMARY INIT
+.\"
+Running as the system manager (primary \fBinit\fR) is currently supported only on
+Linux. When run as process ID 1, the \fBdinit\fR daemon assumes responsibility for
+system shutdown and restart (partially relying on external utilities which are
+part of the Dinit distribution).
+
+When not running as process ID 1, \fBdinit\fR assumes responsibility only for
+service management. System shutdown or restart need to be handled by the primary
+\fBinit\fR, which should start \fBdinit\fR on normal startup, and terminate
+\fBdinit\fR before shutdown, by signalling it and waiting for it to terminate
+after stopping services.
+.\"
 .SH FILES
 .\"
 .TP
@@ -95,12 +108,12 @@ in the environment when Dinit started. Lines beginning with a hash character
 .\"
 .SH SIGNALS
 .LP
-When run as a system process, SIGINT stops all services and performs a reboot (on Linux, this signal can be
+When run as a system manager, 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.
+When run as a user process or system service manager only, SIGINT and SIGTERM both stop services
+and exit Dinit; SIGQUIT exits Dinit immediately.
 .\"
 .SH SEE ALSO
 .\"
index 1f725831fe65040c64f49e37665975bb9f12ad3f..59db0cc39b78c0f141cf65b523ac376f1922db0f 100644 (file)
@@ -65,6 +65,7 @@ static void control_socket_cb(eventloop_t *loop, int fd);
 
 static dirload_service_set *services;
 
+static bool am_pid_one = false;     // true if we are PID 1
 static bool am_system_init = false; // true if we are the system init process
 
 static bool control_socket_open = false;
@@ -168,7 +169,8 @@ int dinit_main(int argc, char **argv)
 {
     using namespace std;
     
-    am_system_init = (getpid() == 1);
+    am_pid_one = (getpid() == 1);
+    am_system_init = (getuid() == 0);
     const char * service_dir = nullptr;
     bool service_dir_dynamic = false; // service_dir dynamically allocated?
     const char * env_file = nullptr;
@@ -286,7 +288,7 @@ int dinit_main(int argc, char **argv)
     sigaddset(&sigwait_set, SIGCHLD);
     sigaddset(&sigwait_set, SIGINT);
     sigaddset(&sigwait_set, SIGTERM);
-    if (am_system_init) sigaddset(&sigwait_set, SIGQUIT);
+    if (am_pid_one) sigaddset(&sigwait_set, SIGQUIT);
     sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
 
     // Terminal access control signals - we block these so that dinit can't be
@@ -334,7 +336,7 @@ int dinit_main(int argc, char **argv)
     callback_signal_handler sigint_watcher;
     callback_signal_handler sigquit_watcher;
 
-    if (am_system_init) {
+    if (am_pid_one) {
         sigint_watcher.setCbFunc(sigint_reboot_cb);
         sigquit_watcher.setCbFunc(sigquit_cb);
     }
@@ -345,7 +347,7 @@ int dinit_main(int argc, char **argv)
     sigint_watcher.add_watch(event_loop, SIGINT);
     sigterm_watcher.add_watch(event_loop, SIGTERM);
     
-    if (am_system_init) {
+    if (am_pid_one) {
         // PID 1: SIGQUIT exec's shutdown
         sigquit_watcher.add_watch(event_loop, SIGQUIT);
         // As a user process, we instead just let SIGQUIT perform the default action.
@@ -429,7 +431,7 @@ int dinit_main(int argc, char **argv)
 
     shutdown_type_t shutdown_type = services->get_shutdown_type();
     
-    if (am_system_init) {
+    if (am_pid_one) {
         log_msg_begin(loglevel_t::INFO, "No more active services.");
         
         if (shutdown_type == shutdown_type_t::REBOOT) {
@@ -453,7 +455,7 @@ int dinit_main(int argc, char **argv)
     
     close_control_socket();
     
-    if (am_system_init) {
+    if (am_pid_one) {
         if (shutdown_type == shutdown_type_t::CONTINUE) {
             // It could be that we started in single user mode, and the
             // user has now exited the shell. We'll try and re-start the