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
.\"
.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
.\"
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;
{
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;
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
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);
}
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.
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) {
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