Fix missing #include (needed for compiling with GCC 10)
[oweals/dinit.git] / src / dinit.cc
1 #include <iostream>
2 #include <fstream>
3 #include <list>
4 #include <cstring>
5 #include <csignal>
6 #include <cstddef>
7 #include <cstdlib>
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <sys/un.h>
12 #include <sys/socket.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <pwd.h>
16 #include <termios.h>
17 #ifdef __linux__
18 #include <sys/prctl.h>
19 #include <sys/klog.h>
20 #include <sys/reboot.h>
21 #endif
22 #if defined(__FreeBSD__) || defined(__DragonFly__)
23 #include <sys/procctl.h>
24 #endif
25
26 #include "dinit.h"
27 #include "dasynq.h"
28 #include "service.h"
29 #include "control.h"
30 #include "dinit-log.h"
31 #include "dinit-socket.h"
32 #include "static-string.h"
33 #include "dinit-utmp.h"
34 #include "options-processing.h"
35
36 #include "mconfig.h"
37
38 /*
39  * When running as the system init process, Dinit processes the following signals:
40  *
41  * SIGTERM - roll back services and then fork/exec /sbin/halt
42  * SIGINT - roll back services and then fork/exec /sbin/reboot
43  * SIGQUIT - exec() /sbin/shutdown without rolling back services
44  *
45  * It's an open question about whether Dinit should roll back services *before*
46  * running halt/reboot, since those commands should prompt rollback of services
47  * anyway. But it seems safe to do so, and it means the user can at least stop
48  * services even if the halt/reboot commands are unavailable for some reason.
49  */
50
51 using namespace cts;
52
53 using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
54
55 eventloop_t event_loop;
56
57 static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
58 static void sigquit_cb(eventloop_t &eloop) noexcept;
59 static void sigterm_cb(eventloop_t &eloop) noexcept;
60 static void open_control_socket(bool report_ro_failure = true) noexcept;
61 static void close_control_socket() noexcept;
62 static void confirm_restart_boot() noexcept;
63
64 static void control_socket_cb(eventloop_t *loop, int fd);
65
66
67 // Variables
68
69 static dirload_service_set *services;
70
71 static bool am_pid_one = false;     // true if we are PID 1
72 static bool am_system_init = false; // true if we are the system init process
73
74 static bool did_log_boot = false;
75 static bool control_socket_open = false;
76 bool external_log_open = false;
77 int active_control_conns = 0;
78
79 // Control socket path. We maintain a string (control_socket_str) in case we need
80 // to allocate storage, but control_socket_path is the authoritative value.
81 static const char *control_socket_path = SYSCONTROLSOCKET;
82 static std::string control_socket_str;
83
84 static const char *env_file_path = "/etc/dinit/environment";
85
86 static const char *log_path = "/dev/log";
87 static bool log_is_syslog = true; // if false, log is a file
88
89 // Set to true (when console_input_watcher is active) if console input becomes available
90 static bool console_input_ready = false;
91
92
93 namespace {
94     // Event-loop handler for a signal, which just delegates to a function (pointer).
95     class callback_signal_handler : public eventloop_t::signal_watcher_impl<callback_signal_handler>
96     {
97         using rearm = dasynq::rearm;
98
99         public:
100         typedef void (*cb_func_t)(eventloop_t &);
101         
102         private:
103         cb_func_t cb_func;
104         
105         public:
106         callback_signal_handler() : cb_func(nullptr) { }
107         callback_signal_handler(cb_func_t pcb_func) :  cb_func(pcb_func) { }
108         
109         void set_cb_func(cb_func_t cb_func)
110         {
111             this->cb_func = cb_func;
112         }
113         
114         rearm received(eventloop_t &eloop, int signo, siginfo_p siginfo)
115         {
116             cb_func(eloop);
117             return rearm::REARM;
118         }
119     };
120
121     // Event-loop handler for when a connection is made to the control socket.
122     class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
123     {
124         using rearm = dasynq::rearm;
125
126         public:
127         rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
128         {
129             control_socket_cb(&loop, fd);
130             return rearm::REARM;
131         }
132     };
133
134     // Watch for console input and set a flag when it is available.
135     class console_input_watcher : public eventloop_t::fd_watcher_impl<console_input_watcher>
136     {
137         using rearm = dasynq::rearm;
138
139         public:
140         rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
141         {
142             console_input_ready = true;
143             return rearm::DISARM;
144         }
145     };
146
147     // Simple timer used to limit the amount of time waiting for the log flush to complete (at shutdown)
148     class log_flush_timer_t : public eventloop_t::timer_impl<log_flush_timer_t>
149     {
150         using rearm = dasynq::rearm;
151
152         bool expired;
153
154         public:
155         rearm timer_expiry(eventloop_t &, int expiry_count)
156         {
157             expired = true;
158             return rearm::DISARM;
159         }
160
161         bool has_expired()
162         {
163             return expired;
164         }
165
166         void reset()
167         {
168             expired = false;
169         }
170     };
171
172     control_socket_watcher control_socket_io;
173     console_input_watcher console_input_io;
174     log_flush_timer_t log_flush_timer;
175
176     // These need to be at namespace scope to prevent causing stack allocations when using them:
177     constexpr auto shutdown_exec = literal(SBINDIR) + "/" + SHUTDOWN_PREFIX + "shutdown";
178     constexpr auto error_exec_sd = literal("Error executing ") + shutdown_exec + ": ";
179 }
180
181 // Main entry point
182 int dinit_main(int argc, char **argv)
183 {
184     using namespace std;
185     
186     am_pid_one = (getpid() == 1);
187     am_system_init = (getuid() == 0);
188     const char * env_file = nullptr;
189     bool control_socket_path_set = false;
190     bool env_file_set = false;
191     bool log_specified = false;
192
193     service_dir_opt service_dir_opts;
194
195     // list of services to start
196     list<const char *> services_to_start;
197     
198     // Arguments, if given, specify a list of services to start.
199     // If we are running as init (PID=1), the Linux kernel gives us any command line arguments it was given
200     // but didn't recognize, including "single" (usually for "boot to single user mode" aka just start the
201     // shell). We can treat them as service names. In the worst case we can't find any of the named
202     // services, and so we'll start the "boot" service by default.
203     if (argc > 1) {
204         for (int i = 1; i < argc; i++) {
205             if (argv[i][0] == '-') {
206                 // An option...
207                 if (strcmp(argv[i], "--env-file") == 0 || strcmp(argv[i], "-e") == 0) {
208                     if (++i < argc) {
209                         env_file_set = true;
210                         env_file = argv[i];
211                     }
212                     else {
213                         cerr << "dinit: '--env-file' (-e) requires an argument" << endl;
214                     }
215                 }
216                 else if (strcmp(argv[i], "--services-dir") == 0 || strcmp(argv[i], "-d") == 0) {
217                     if (++i < argc) {
218                         service_dir_opts.set_specified_service_dir(argv[i]);
219                     }
220                     else {
221                         cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
222                         return 1;
223                     }
224                 }
225                 else if (strcmp(argv[i], "--system") == 0 || strcmp(argv[i], "-s") == 0) {
226                     am_system_init = true;
227                 }
228                 else if (strcmp(argv[i], "--user") == 0 || strcmp(argv[i], "-u") == 0) {
229                     am_system_init = false;
230                 }
231                 else if (strcmp(argv[i], "--socket-path") == 0 || strcmp(argv[i], "-p") == 0) {
232                     if (++i < argc) {
233                         control_socket_path = argv[i];
234                         control_socket_path_set = true;
235                     }
236                     else {
237                         cerr << "dinit: '--socket-path' (-p) requires an argument" << endl;
238                         return 1;
239                     }
240                 }
241                 else if (strcmp(argv[i], "--log-file") == 0 || strcmp(argv[i], "-l") == 0) {
242                     if (++i < argc) {
243                         log_path = argv[i];
244                         log_is_syslog = false;
245                         log_specified = true;
246                     }
247                     else {
248                         cerr << "dinit: '--log-file' (-l) requires an argument" << endl;
249                         return 1;
250                     }
251                 }
252                 else if (strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "-q") == 0) {
253                     console_service_status = false;
254                     log_level[DLOG_CONS] = loglevel_t::ZERO;
255                 }
256                 else if (strcmp(argv[i], "--help") == 0) {
257                     cout << "dinit, an init with dependency management\n"
258                             " --help                       display help\n"
259                             " --env-file <file>, -e <file>\n"
260                             "                              environment variable initialisation file\n"
261                             " --services-dir <dir>, -d <dir>\n"
262                             "                              set base directory for service description\n"
263                             "                              files\n"
264                             " --system, -s                 run as the system service manager\n"
265                             " --user, -u                   run as a user service manager\n"
266                             " --socket-path <path>, -p <path>\n"
267                             "                              path to control socket\n"
268                             " --log-file <file>, -l <file> log to the specified file\n"
269                             " --quiet, -q                  disable output to standard output\n"
270                             " <service-name>               start service with name <service-name>\n";
271                     return 0;
272                 }
273                 else {
274                     // unrecognized
275                     if (! am_system_init) {
276                         cerr << "dinit: Unrecognized option: " << argv[i] << endl;
277                         return 1;
278                     }
279                 }
280             }
281             else {
282 #ifdef __linux__
283                 // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
284                 if (! am_pid_one || strcmp(argv[i], "auto") != 0) {
285                     services_to_start.push_back(argv[i]);
286                 }
287 #else
288                 services_to_start.push_back(argv[i]);
289 #endif
290             }
291         }
292     }
293     
294     if (am_system_init) {
295         // setup STDIN, STDOUT, STDERR so that we can use them
296         int onefd = open("/dev/console", O_RDONLY, 0);
297         if (onefd != -1) {
298             dup2(onefd, 0);
299         }
300         int twofd = open("/dev/console", O_RDWR, 0);
301         if (twofd != -1) {
302             dup2(twofd, 1);
303             dup2(twofd, 2);
304         }
305         
306         if (onefd > 2) close(onefd);
307         if (twofd > 2) close(twofd);
308
309         if (! env_file_set) {
310             env_file = env_file_path;
311         }
312     }
313
314     /* Set up signal handlers etc */
315     /* SIG_CHILD is ignored by default: good */
316     sigset_t sigwait_set;
317     sigemptyset(&sigwait_set);
318     sigaddset(&sigwait_set, SIGCHLD);
319     sigaddset(&sigwait_set, SIGINT);
320     sigaddset(&sigwait_set, SIGTERM);
321     if (am_pid_one) sigaddset(&sigwait_set, SIGQUIT);
322     sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
323
324     // Terminal access control signals - we ignore these so that dinit can't be
325     // suspended if it writes to the terminal after some other process has claimed
326     // ownership of it.
327     signal(SIGTSTP, SIG_IGN);
328     signal(SIGTTIN, SIG_IGN);
329     signal(SIGTTOU, SIG_IGN);
330     
331     signal(SIGPIPE, SIG_IGN);
332     
333     if (! am_system_init && ! control_socket_path_set) {
334         const char * userhome = service_dir_opt::get_user_home();
335         if (userhome != nullptr) {
336             control_socket_str = userhome;
337             control_socket_str += "/.dinitctl";
338             control_socket_path = control_socket_str.c_str();
339         }
340     }
341     
342     if (services_to_start.empty()) {
343         services_to_start.push_back("boot");
344     }
345
346     // Set up signal handlers
347     callback_signal_handler sigterm_watcher {sigterm_cb};
348     callback_signal_handler sigint_watcher;
349     callback_signal_handler sigquit_watcher;
350
351     if (am_pid_one) {
352         sigint_watcher.set_cb_func(sigint_reboot_cb);
353         sigquit_watcher.set_cb_func(sigquit_cb);
354     }
355     else {
356         sigint_watcher.set_cb_func(sigterm_cb);
357     }
358
359     sigint_watcher.add_watch(event_loop, SIGINT);
360     sigterm_watcher.add_watch(event_loop, SIGTERM);
361     
362     if (am_pid_one) {
363         // PID 1: we may ask for console input; SIGQUIT exec's shutdown
364         console_input_io.add_watch(event_loop, STDIN_FILENO, dasynq::IN_EVENTS, false);
365         sigquit_watcher.add_watch(event_loop, SIGQUIT);
366         // (If not PID 1, we instead just let SIGQUIT perform the default action.)
367     }
368
369     // Try to open control socket (may fail due to readonly filesystem)
370     open_control_socket(false);
371     
372 #ifdef __linux__
373     if (am_system_init) {
374         // Disable non-critical kernel output to console
375         klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
376         // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
377         reboot(RB_DISABLE_CAD);
378     }
379
380     // Mark ourselves as a subreaper. This means that if a process we start double-forks, the
381     // orphaned child will re-parent to us rather than to PID 1 (although that could be us too).
382     prctl(PR_SET_CHILD_SUBREAPER, 1);
383 #elif defined(__FreeBSD__) || defined(__DragonFly__)
384     // Documentation (man page) for this kind of sucks. PROC_REAP_ACQUIRE "acquires the reaper status for
385     // the current process" but does that mean the first two arguments still need valid values to be
386     // supplied? We'll play it safe and explicitly target our own process:
387     procctl(P_PID, getpid(), PROC_REAP_ACQUIRE, NULL);
388 #endif
389     
390     log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
391
392     service_dir_opts.build_paths(am_system_init);
393
394     /* start requested services */
395     services = new dirload_service_set(std::move(service_dir_opts.get_paths()));
396
397     init_log(services, log_is_syslog);
398     if (am_system_init) {
399         log(loglevel_t::INFO, false, "Starting system");
400     }
401     
402     // Only try to set up the external log now if we aren't the system init. (If we are the
403     // system init, wait until the log service starts).
404     if (! am_system_init && log_specified) setup_external_log();
405
406     if (env_file != nullptr) {
407         read_env_file(env_file);
408     }
409
410     for (auto svc : services_to_start) {
411         try {
412             services->start_service(svc);
413             // Note in general if we fail to start a service we don't need any special error handling,
414             // since we either leave other services running or, if it was the only service, then no
415             // services will be running and we will process normally (reboot if system process,
416             // exit if user process).
417         }
418         catch (service_not_found &snf) {
419             log(loglevel_t::ERROR, snf.service_name, ": Could not find service description.");
420         }
421         catch (service_load_exc &sle) {
422             log(loglevel_t::ERROR, sle.service_name, ": ", sle.exc_description);
423         }
424         catch (std::bad_alloc &badalloce) {
425             log(loglevel_t::ERROR, "Out of memory when trying to start service: ", svc, ".");
426             break;
427         }
428     }
429     
430     run_event_loop:
431     
432     // Process events until all services have terminated.
433     while (services->count_active_services() != 0) {
434         event_loop.run();
435     }
436
437     shutdown_type_t shutdown_type = services->get_shutdown_type();
438     if (shutdown_type == shutdown_type_t::REMAIN) {
439         goto run_event_loop;
440     }
441     
442     if (am_pid_one) {
443         log_msg_begin(loglevel_t::INFO, "No more active services.");
444         
445         if (shutdown_type == shutdown_type_t::REBOOT) {
446             log_msg_end(" Will reboot.");
447         }
448         else if (shutdown_type == shutdown_type_t::HALT) {
449             log_msg_end(" Will halt.");
450         }
451         else if (shutdown_type == shutdown_type_t::POWEROFF) {
452             log_msg_end(" Will power down.");
453         }
454     }
455     
456     log_flush_timer.reset();
457     log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
458     while (! is_log_flushed() && ! log_flush_timer.has_expired()) {
459         event_loop.run();
460     }
461     
462     close_control_socket();
463     
464     if (am_pid_one) {
465         if (shutdown_type == shutdown_type_t::NONE) {
466             // Services all stopped but there was no shutdown issued. Inform user, wait for ack, and
467             // re-start boot sequence.
468             sync(); // Sync to minimise data loss if user elects to power off / hard reset
469             confirm_restart_boot();
470             if (services->count_active_services() != 0) {
471                 // Recovery service started
472                 goto run_event_loop;
473             }
474             shutdown_type = services->get_shutdown_type();
475             if (shutdown_type == shutdown_type_t::NONE) {
476                 try {
477                     services->start_service("boot");
478                     goto run_event_loop; // yes, the "evil" goto
479                 }
480                 catch (...) {
481                     // Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
482                     log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
483                     shutdown_type = shutdown_type_t::REBOOT;
484                 }
485             }
486         }
487         
488         const char * cmd_arg;
489         if (shutdown_type == shutdown_type_t::HALT) {
490             cmd_arg = "-h";
491         }
492         else if (shutdown_type == shutdown_type_t::REBOOT) {
493             cmd_arg = "-r";
494         }
495         else {
496             // power off.
497             cmd_arg = "-p";
498         }
499         
500         // Fork and execute dinit-reboot.
501         execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", cmd_arg, nullptr);
502         log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
503         
504         // PID 1 must not actually exit, although we should never reach this point:
505         while (true) {
506             event_loop.run();
507         }
508     }
509     else if (shutdown_type == shutdown_type_t::REBOOT) {
510         // Non-system-process. If we got SIGINT, let's die due to it:
511         sigset_t sigwait_set_int;
512         sigemptyset(&sigwait_set_int);
513         sigaddset(&sigwait_set_int, SIGINT);
514         raise(SIGINT);
515         sigprocmask(SIG_UNBLOCK, &sigwait_set_int, NULL);
516     }
517     
518     return 0;
519 }
520
521 // Log a parse error when reading the environment file.
522 static void log_bad_env(int linenum)
523 {
524     log(loglevel_t::ERROR, "invalid environment variable setting in environment file (line ", linenum, ")");
525 }
526
527 // Read and set environment variables from a file. May throw std::bad_alloc, std::system_error.
528 void read_env_file(const char *env_file_path)
529 {
530     // Note that we can't use the log in this function; it hasn't been initialised yet.
531
532     std::ifstream env_file(env_file_path);
533     if (! env_file) return;
534
535     env_file.exceptions(std::ios::badbit);
536
537     auto &clocale = std::locale::classic();
538     std::string line;
539     int linenum = 0;
540
541     while (std::getline(env_file, line)) {
542         linenum++;
543         auto lpos = line.begin();
544         auto lend = line.end();
545         while (lpos != lend && std::isspace(*lpos, clocale)) {
546             ++lpos;
547         }
548
549         if (lpos != lend) {
550             if (*lpos != '#') {
551                 if (*lpos == '=') {
552                     log_bad_env(linenum);
553                     continue;
554                 }
555                 auto name_begin = lpos++;
556                 // skip until '=' or whitespace:
557                 while (lpos != lend && *lpos != '=' && ! std::isspace(*lpos, clocale)) ++lpos;
558                 auto name_end = lpos;
559                 //  skip whitespace:
560                 while (lpos != lend && std::isspace(*lpos, clocale)) ++lpos;
561                 if (lpos == lend) {
562                     log_bad_env(linenum);
563                     continue;
564                 }
565
566                 ++lpos;
567                 auto val_begin = lpos;
568                 while (lpos != lend && *lpos != '\n') ++lpos;
569                 auto val_end = lpos;
570
571                 std::string name = line.substr(name_begin - line.begin(), name_end - name_begin);
572                 std::string value = line.substr(val_begin - line.begin(), val_end - val_begin);
573                 if (setenv(name.c_str(), value.c_str(), true) == -1) {
574                     throw std::system_error(errno, std::system_category());
575                 }
576             }
577         }
578     }
579 }
580
581 // Get user confirmation before proceeding with restarting boot sequence.
582 // Returns after confirmation, possibly with shutdown type altered.
583 static void confirm_restart_boot() noexcept
584 {
585     // Bypass log; we want to make certain the message is seen:
586     std::cout << "All services have stopped with no shutdown issued; boot failure?\n";
587
588     // Drain input, set non-canonical input mode (receive characters as they are typed)
589     struct termios term_attr;
590     if (tcgetattr(STDIN_FILENO, &term_attr) != 0) {
591         // Not a terminal?
592         std::cout << "Halting." << std::endl;
593         services->stop_all_services(shutdown_type_t::HALT);
594         return;
595     }
596     term_attr.c_lflag &= ~ICANON;
597     tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr);
598
599     // Set non-blocking mode
600     int origFlags = fcntl(STDIN_FILENO, F_GETFL);
601     fcntl(STDIN_FILENO, F_SETFL, origFlags | O_NONBLOCK);
602
603     do_prompt:
604     std::cout << "Choose: (r)eboot, r(e)covery, re(s)tart boot sequence, (p)ower off? " << std::flush;
605
606     console_input_io.set_enabled(event_loop, true);
607     do {
608         event_loop.run();
609     } while (! console_input_ready && services->get_shutdown_type() == shutdown_type_t::NONE);
610     console_input_io.set_enabled(event_loop, false);
611
612     // We either have input, or shutdown type has been set, or both.
613     if (console_input_ready) {
614         console_input_ready = false;
615         char buf[1];
616         int r = read(STDIN_FILENO, buf, 1);  // read a single character, to make sure we wait for input
617         if (r == 1) {
618             std::cout << "\n"; // force new line after input
619             if (buf[0] == 'r' || buf[0] == 'R') {
620                 services->stop_all_services(shutdown_type_t::REBOOT);
621             }
622             else if (buf[0] == 'e' || buf[0] == 'E') {
623                 try {
624                     services->start_service("recovery");
625                 }
626                 catch (...) {
627                     std::cout << "Unable to start recovery service.\n";
628                     goto do_prompt;
629                 }
630             }
631             else if (buf[0] == 's' || buf[0] == 'S') {
632                 // nothing - leave no shutdown type
633             }
634             else if (buf[0] == 'p' || buf[0] == 'P') {
635                 services->stop_all_services(shutdown_type_t::POWEROFF);
636             }
637             else {
638                 goto do_prompt;
639             }
640         }
641         tcflush(STDIN_FILENO, TCIFLUSH); // discard the rest of input
642     }
643
644     term_attr.c_lflag |= ICANON;
645     tcsetattr(STDIN_FILENO, TCSANOW, &term_attr);
646     fcntl(STDIN_FILENO, F_SETFL, origFlags);
647 }
648
649 // Callback for control socket
650 static void control_socket_cb(eventloop_t *loop, int sockfd)
651 {
652     // Considered keeping a limit the number of active connections, however, there doesn't
653     // seem much to be gained from that. Only root can create connections and not being
654     // able to establish a control connection is as much a denial-of-service as is not being
655     // able to start a service due to lack of fd's.
656
657     // Accept a connection
658     int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
659
660     if (newfd != -1) {
661         try {
662             new control_conn_t(*loop, services, newfd);  // will delete itself when it's finished
663         }
664         catch (std::exception &exc) {
665             log(loglevel_t::ERROR, "Accepting control connection: ", exc.what());
666             close(newfd);
667         }
668     }
669 }
670
671 // Callback when the root filesystem is read/write:
672 void rootfs_is_rw() noexcept
673 {
674     open_control_socket(true);
675     if (! did_log_boot) {
676         did_log_boot = log_boot();
677     }
678 }
679
680 // Open/create the control socket, normally /dev/dinitctl, used to allow client programs to connect
681 // and issue service orders and shutdown commands etc. This can safely be called multiple times;
682 // once the socket has been successfully opened, further calls have no effect.
683 static void open_control_socket(bool report_ro_failure) noexcept
684 {
685     if (control_socket_open) {
686         struct stat stat_buf;
687         if (stat(control_socket_path, &stat_buf) != 0 && errno == ENOENT) {
688             // Looks like our control socket has disappeared from the filesystem. Close our control
689             // socket and re-create it:
690             control_socket_io.deregister(event_loop);
691             close(control_socket_io.get_watched_fd());
692             control_socket_open = false; // now re-open below
693         }
694     }
695
696     if (! control_socket_open) {
697         const char * saddrname = control_socket_path;
698         size_t saddrname_len = strlen(saddrname);
699         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
700         
701         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
702         if (name == nullptr) {
703             log(loglevel_t::ERROR, "Opening control socket: out of memory");
704             return;
705         }
706
707         if (am_system_init) {
708             // Unlink any stale control socket file, but only if we are system init, since otherwise
709             // the 'stale' file may not be stale at all:
710             unlink(saddrname);
711         }
712
713         name->sun_family = AF_UNIX;
714         memcpy(name->sun_path, saddrname, saddrname_len + 1);
715
716         int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
717         if (sockfd == -1) {
718             log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
719             free(name);
720             return;
721         }
722
723         if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
724             if (errno != EROFS || report_ro_failure) {
725                 log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
726             }
727             close(sockfd);
728             free(name);
729             return;
730         }
731         
732         free(name);
733
734         // No connections can be made until we listen, so it is fine to change the permissions now
735         // (and anyway there is no way to atomically create the socket and set permissions):
736         if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
737             log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
738             close(sockfd);
739             return;
740         }
741
742         if (listen(sockfd, 10) == -1) {
743             log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
744             close(sockfd);
745             return;
746         }
747
748         try {
749             control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
750             control_socket_open = true;
751         }
752         catch (std::exception &e)
753         {
754             log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
755             close(sockfd);
756         }
757     }
758 }
759
760 static void close_control_socket() noexcept
761 {
762     if (control_socket_open) {
763         int fd = control_socket_io.get_watched_fd();
764         control_socket_io.deregister(event_loop);
765         close(fd);
766         
767         // Unlink the socket:
768         unlink(control_socket_path);
769
770         control_socket_open = false;
771     }
772 }
773
774 void setup_external_log() noexcept
775 {
776     if (! external_log_open) {
777         if (log_is_syslog) {
778             const char * saddrname = log_path;
779             size_t saddrname_len = strlen(saddrname);
780             uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
781
782             struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
783             if (name == nullptr) {
784                 log(loglevel_t::ERROR, "Connecting to log socket: out of memory");
785                 return;
786             }
787
788             name->sun_family = AF_UNIX;
789             memcpy(name->sun_path, saddrname, saddrname_len + 1);
790
791             int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
792             if (sockfd == -1) {
793                 log(loglevel_t::ERROR, "Error creating log socket: ", strerror(errno));
794                 free(name);
795                 return;
796             }
797
798             if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
799                 // For EINPROGRESS, connection is still being established; however, we can select on
800                 // the file descriptor so we will be notified when it's ready. In other words we can
801                 // basically use it anyway.
802                 try {
803                     setup_main_log(sockfd);
804                     external_log_open = true;
805                 }
806                 catch (std::exception &e) {
807                     log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
808                     close(sockfd);
809                 }
810             }
811             else {
812                 // Note if connect fails, we haven't warned at all, because the syslog server might not
813                 // have started yet.
814                 close(sockfd);
815             }
816
817             free(name);
818         }
819         else {
820             // log to file:
821             int log_fd = open(log_path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK | O_CLOEXEC, 0644);
822             if (log_fd >= 0) {
823                 try {
824                     setup_main_log(log_fd);
825                     external_log_open = true;
826                 }
827                 catch (std::exception &e) {
828                     log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
829                     close(log_fd);
830                 }
831             }
832             else {
833                 // log failure to log? It makes more sense than first appears, because we also log
834                 // to console:
835                 log(loglevel_t::ERROR, "Setting up log failed: ", strerror(errno));
836             }
837         }
838     }
839 }
840
841 /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
842 static void sigint_reboot_cb(eventloop_t &eloop) noexcept
843 {
844     services->stop_all_services(shutdown_type_t::REBOOT);
845 }
846
847 /* handle SIGQUIT (if we are system init) */
848 static void sigquit_cb(eventloop_t &eloop) noexcept
849 {
850     // This performs an immediate shutdown, without service rollback.
851     close_control_socket();
852     execl(shutdown_exec.c_str(), shutdown_exec.c_str(), "--system", (char *) 0);
853     log(loglevel_t::ERROR, error_exec_sd, strerror(errno));
854     sync(); // since a hard poweroff might be required at this point...
855 }
856
857 /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
858 static void sigterm_cb(eventloop_t &eloop) noexcept
859 {
860     services->stop_all_services();
861 }