Mark as a subreaper on FreeBSD (as for Linux).
[oweals/dinit.git] / src / dinit.cc
1 #include <iostream>
2 #include <list>
3 #include <cstring>
4 #include <csignal>
5 #include <cstddef>
6 #include <cstdlib>
7
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/un.h>
11 #include <sys/socket.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <pwd.h>
15 #ifdef __linux__
16 #include <sys/prctl.h>
17 #include <sys/klog.h>
18 #include <sys/reboot.h>
19 #endif
20 #if defined(__FreeBSD__) || defined(__DragonFly__)
21 #include <sys/procctl.h>
22 #endif
23
24 #include "dinit.h"
25 #include "dasynq.h"
26 #include "service.h"
27 #include "control.h"
28 #include "dinit-log.h"
29 #include "dinit-socket.h"
30
31 /*
32  * When running as the system init process, Dinit processes the following signals:
33  *
34  * SIGTERM - roll back services and then fork/exec /sbin/halt
35  * SIGINT - roll back services and then fork/exec /sbin/reboot
36  * SIGQUIT - exec() /sbin/shutdown without rolling back services
37  *
38  * It's an open question about whether Dinit should roll back services *before*
39  * running halt/reboot, since those commands should prompt rollback of services
40  * anyway. But it seems safe to do so, and it means the user can at least stop
41  * services even if the halt/reboot commands are unavailable for some reason.
42  */
43
44 using eventloop_t = dasynq::event_loop<dasynq::null_mutex>;
45
46 eventloop_t event_loop;
47
48 static void sigint_reboot_cb(eventloop_t &eloop) noexcept;
49 static void sigquit_cb(eventloop_t &eloop) noexcept;
50 static void sigterm_cb(eventloop_t &eloop) noexcept;
51 static void close_control_socket() noexcept;
52 static void wait_for_user_input() noexcept;
53
54 static void control_socket_cb(eventloop_t *loop, int fd);
55
56
57 // Variables
58
59 static dirload_service_set *services;
60
61 static bool am_system_init = false; // true if we are the system init process
62
63 static bool control_socket_open = false;
64 static bool external_log_open = false;
65 int active_control_conns = 0;
66
67 // Control socket path. We maintain a string (control_socket_str) in case we need
68 // to allocate storage, but control_socket_path is the authoritative value.
69 static const char *control_socket_path = "/dev/dinitctl";
70 static std::string control_socket_str;
71
72 static const char *log_socket_path = "/dev/log";
73
74 static const char *user_home_path = nullptr;
75
76
77 // Get user home (and set user_home_path). (The return may become invalid after
78 // changing the evironment (HOME variable) or using the getpwuid() function).
79 const char * get_user_home()
80 {
81     if (user_home_path == nullptr) {
82         user_home_path = getenv("HOME");
83         if (user_home_path == nullptr) {
84             struct passwd * pwuid_p = getpwuid(getuid());
85             if (pwuid_p != nullptr) {
86                 user_home_path = pwuid_p->pw_dir;
87             }
88         }
89     }
90     return user_home_path;
91 }
92
93
94 namespace {
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 setCbFunc(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     class control_socket_watcher : public eventloop_t::fd_watcher_impl<control_socket_watcher>
122     {
123         using rearm = dasynq::rearm;
124
125         public:
126         rearm fd_event(eventloop_t &loop, int fd, int flags) noexcept
127         {
128             control_socket_cb(&loop, fd);
129             return rearm::REARM;
130         }
131     };
132
133     // Simple timer used to limit the amount of time waiting for the log flush to complete (at shutdown)
134     class log_flush_timer_t : public eventloop_t::timer_impl<log_flush_timer_t>
135     {
136         using rearm = dasynq::rearm;
137
138         bool expired = false;
139
140         public:
141         rearm timer_expiry(eventloop_t &, int expiry_count)
142         {
143             expired = true;
144             return rearm::DISARM;
145         }
146
147         bool has_expired()
148         {
149             return expired;
150         }
151     };
152
153     control_socket_watcher control_socket_io;
154     log_flush_timer_t log_flush_timer;
155 }
156
157 int dinit_main(int argc, char **argv)
158 {
159     using namespace std;
160     
161     am_system_init = (getpid() == 1);
162     const char * service_dir = nullptr;
163     string service_dir_str; // to hold storage for above if necessary
164     bool control_socket_path_set = false;
165
166     // list of services to start
167     list<const char *> services_to_start;
168     
169     // Arguments, if given, specify a list of services to start.
170     // If we are running as init (PID=1), the kernel gives us any command line
171     // arguments it was given but didn't recognize, including "single" (usually
172     // for "boot to single user mode" aka just start the shell). We can treat
173     // them as service names. In the worst case we can't find any of the named
174     // services, and so we'll start the "boot" service by default.
175     if (argc > 1) {
176       for (int i = 1; i < argc; i++) {
177         if (argv[i][0] == '-') {
178             // An option...
179             if (strcmp(argv[i], "--services-dir") == 0 ||
180                     strcmp(argv[i], "-d") == 0) {
181                 if (++i < argc) {
182                     service_dir = argv[i];
183                 }
184                 else {
185                     cerr << "dinit: '--services-dir' (-d) requires an argument" << endl;
186                     return 1;
187                 }
188             }
189             else if (strcmp(argv[i], "--system") == 0 ||
190                     strcmp(argv[i], "-s") == 0) {
191                 am_system_init = true;
192             }
193             else if (strcmp(argv[i], "--socket-path") == 0 ||
194                     strcmp(argv[i], "-p") == 0) {
195                 if (++i < argc) {
196                     control_socket_path = argv[i];
197                     control_socket_path_set = true;
198                 }
199                 else {
200                     cerr << "dinit: '--socket-path' (-p) requires an argument" << endl;
201                     return 1;
202                 }
203             }
204             else if (strcmp(argv[i], "--help") == 0) {
205                 cout << "dinit, an init with dependency management" << endl;
206                 cout << " --help                       display help" << endl;
207                 cout << " --services-dir <dir>, -d <dir>" << endl;
208                 cout << "                              set base directory for service description" << endl;
209                 cout << "                              files (-d <dir>)" << endl;
210                 cout << " --system, -s                 run as the system init process" << endl;
211                 cout << " --socket-path <path>, -p <path>" << endl;
212                 cout << "                              path to control socket" << endl;
213                 cout << " <service-name>               start service with name <service-name>" << endl;
214                 return 0;
215             }
216             else {
217                 // unrecognized
218                 if (! am_system_init) {
219                     cerr << "dinit: Unrecognized option: " << argv[i] << endl;
220                     return 1;
221                 }
222             }
223         }
224         else {
225 #ifdef __linux__
226             // LILO puts "auto" on the kernel command line for unattended boots; we'll filter it.
227             if (! am_system_init || strcmp(argv[i], "auto") != 0) {
228                 services_to_start.push_back(argv[i]);
229             }
230 #endif
231         }
232       }
233     }
234     
235     if (am_system_init) {
236         // setup STDIN, STDOUT, STDERR so that we can use them
237         int onefd = open("/dev/console", O_RDONLY, 0);
238         dup2(onefd, 0);
239         int twofd = open("/dev/console", O_RDWR, 0);
240         dup2(twofd, 1);
241         dup2(twofd, 2);
242         
243         if (onefd > 2) close(onefd);
244         if (twofd > 2) close(twofd);
245     }
246
247     /* Set up signal handlers etc */
248     /* SIG_CHILD is ignored by default: good */
249     sigset_t sigwait_set;
250     sigemptyset(&sigwait_set);
251     sigaddset(&sigwait_set, SIGCHLD);
252     sigaddset(&sigwait_set, SIGINT);
253     sigaddset(&sigwait_set, SIGTERM);
254     if (am_system_init) sigaddset(&sigwait_set, SIGQUIT);
255     sigprocmask(SIG_BLOCK, &sigwait_set, NULL);
256
257     // Terminal access control signals - we block these so that dinit can't be
258     // suspended if it writes to the terminal after some other process has claimed
259     // ownership of it.
260     signal(SIGTSTP, SIG_IGN);
261     signal(SIGTTIN, SIG_IGN);
262     signal(SIGTTOU, SIG_IGN);
263     
264     signal(SIGPIPE, SIG_IGN);
265     
266     if (! am_system_init && ! control_socket_path_set) {
267         const char * userhome = get_user_home();
268         if (userhome != nullptr) {
269             control_socket_str = userhome;
270             control_socket_str += "/.dinitctl";
271             control_socket_path = control_socket_str.c_str();
272         }
273     }
274     
275     /* service directory name */
276     if (service_dir == nullptr && ! am_system_init) {
277         const char * userhome = get_user_home();
278         if (userhome != nullptr) {
279             service_dir_str = get_user_home();
280             service_dir_str += "/dinit.d";
281             service_dir = service_dir_str.c_str();
282         }
283     }
284     
285     if (service_dir == nullptr) {
286         service_dir = "/etc/dinit.d";
287     }
288     
289     if (services_to_start.empty()) {
290         services_to_start.push_back("boot");
291     }
292
293     // Set up signal handlers
294     callback_signal_handler sigterm_watcher {sigterm_cb};
295     callback_signal_handler sigint_watcher;
296     callback_signal_handler sigquit_watcher;
297
298     if (am_system_init) {
299         sigint_watcher.setCbFunc(sigint_reboot_cb);
300         sigquit_watcher.setCbFunc(sigquit_cb);
301     }
302     else {
303         sigint_watcher.setCbFunc(sigterm_cb);
304     }
305
306     sigint_watcher.add_watch(event_loop, SIGINT);
307     sigterm_watcher.add_watch(event_loop, SIGTERM);
308     
309     if (am_system_init) {
310         // PID 1: SIGQUIT exec's shutdown
311         sigquit_watcher.add_watch(event_loop, SIGQUIT);
312         // As a user process, we instead just let SIGQUIT perform the default action.
313     }
314
315     // Try to open control socket (may fail due to readonly filesystem)
316     open_control_socket(false);
317     
318 #ifdef __linux__
319     if (am_system_init) {
320         // Disable non-critical kernel output to console
321         klogctl(6 /* SYSLOG_ACTION_CONSOLE_OFF */, nullptr, 0);
322         // Make ctrl+alt+del combination send SIGINT to PID 1 (this process)
323         reboot(RB_DISABLE_CAD);
324     }
325
326     // Mark ourselves as a subreaper. This means that if a process we start double-forks, the
327     // orphaned child will re-parent to us rather than to PID 1 (although that could be us too).
328     prctl(PR_SET_CHILD_SUBREAPER, 1);
329 #endif
330 #if defined(__FreeBSD__) || defined(__DragonFly__)
331     // Documentation (man page) for this kind of sucks. PROC_REAP_ACQUIRE "acquires the reaper status for
332     // the current process" but does that mean the first two arguments still need valid values to be
333     // supplied? We'll play itself and explicitly target our own process:
334     procctl(P_PID, getpid(), PROC_REAP_ACQUIRE);
335 #endif
336     
337     log_flush_timer.add_timer(event_loop, dasynq::clock_type::MONOTONIC);
338
339     /* start requested services */
340     services = new dirload_service_set(service_dir);
341     
342     init_log(services);
343     
344     for (auto svc : services_to_start) {
345         try {
346             services->start_service(svc);
347             // Note in general if we fail to start a service we don't need any special error handling,
348             // since we either leave other services running or, if it was the only service, then no
349             // services will be running and we will process normally (reboot if system process,
350             // exit if user process).
351         }
352         catch (service_not_found &snf) {
353             log(loglevel_t::ERROR, snf.serviceName, ": Could not find service description.");
354         }
355         catch (service_load_exc &sle) {
356             log(loglevel_t::ERROR, sle.serviceName, ": ", sle.excDescription);
357         }
358         catch (std::bad_alloc &badalloce) {
359             log(loglevel_t::ERROR, "Out of memory when trying to start service: ", svc, ".");
360             break;
361         }
362     }
363     
364     event_loop:
365     
366     // Process events until all services have terminated.
367     while (services->count_active_services() != 0) {
368         event_loop.run();
369     }
370
371     shutdown_type_t shutdown_type = services->get_shutdown_type();
372     
373     if (am_system_init) {
374         log_msg_begin(loglevel_t::INFO, "No more active services.");
375         
376         if (shutdown_type == shutdown_type_t::REBOOT) {
377             log_msg_end(" Will reboot.");
378         }
379         else if (shutdown_type == shutdown_type_t::HALT) {
380             log_msg_end(" Will halt.");
381         }
382         else if (shutdown_type == shutdown_type_t::POWEROFF) {
383             log_msg_end(" Will power down.");
384         }
385         else {
386             log_msg_end(" Re-initiating boot sequence.");
387         }
388     }
389     
390     log_flush_timer.arm_timer_rel(event_loop, timespec{5,0}); // 5 seconds
391     while (! is_log_flushed() && ! log_flush_timer.has_expired()) {
392         event_loop.run();
393     }
394     
395     close_control_socket();
396     
397     if (am_system_init) {
398         if (shutdown_type == shutdown_type_t::CONTINUE) {
399             // It could be that we started in single user mode, and the
400             // user has now exited the shell. We'll try and re-start the
401             // boot process...
402             try {
403                 services->start_service("boot");
404                 goto event_loop; // yes, the "evil" goto
405             }
406             catch (...) {
407                 // Now what do we do? try to reboot, but wait for user ack to avoid boot loop.
408                 log(loglevel_t::ERROR, "Could not start 'boot' service. Will attempt reboot.");
409                 wait_for_user_input();
410                 shutdown_type = shutdown_type_t::REBOOT;
411             }
412         }
413         
414         const char * cmd_arg;
415         if (shutdown_type == shutdown_type_t::HALT) {
416             cmd_arg = "-h";
417         }
418         else if (shutdown_type == shutdown_type_t::REBOOT) {
419             cmd_arg = "-r";
420         }
421         else {
422             // power off.
423             cmd_arg = "-p";
424         }
425         
426         // Fork and execute dinit-reboot.
427         execl("/sbin/shutdown", "/sbin/shutdown", "--system", cmd_arg, nullptr);
428         log(loglevel_t::ERROR, "Could not execute /sbin/shutdown: ", strerror(errno));
429         
430         // PID 1 must not actually exit, although we should never reach this point:
431         while (true) {
432             event_loop.run();
433         }
434     }
435     else if (shutdown_type == shutdown_type_t::REBOOT) {
436         // Non-system-process. If we got SIGINT, let's die due to it:
437         sigset_t sigwait_set;
438         sigemptyset(&sigwait_set);
439         sigaddset(&sigwait_set, SIGINT);
440         raise(SIGINT);
441         sigprocmask(SIG_UNBLOCK, &sigwait_set, NULL);
442     }
443     
444     return 0;
445 }
446
447 // In exception situations we want user confirmation before proceeding (eg on critical boot failure
448 // we wait before rebooting to avoid a reboot loop).
449 static void wait_for_user_input() noexcept
450 {
451     std::cout << "Press Enter to continue." << std::endl;
452     char buf[1];
453     read(STDIN_FILENO, buf, 1);
454 }
455
456 // Callback for control socket
457 static void control_socket_cb(eventloop_t *loop, int sockfd)
458 {
459     // Considered keeping a limit the number of active connections, however, there doesn't
460     // seem much to be gained from that. Only root can create connections and not being
461     // able to establish a control connection is as much a denial-of-service as is not being
462     // able to start a service due to lack of fd's.
463
464     // Accept a connection
465     int newfd = dinit_accept4(sockfd, nullptr, nullptr, SOCK_NONBLOCK | SOCK_CLOEXEC);
466
467     if (newfd != -1) {
468         try {
469             new control_conn_t(*loop, services, newfd);  // will delete itself when it's finished
470         }
471         catch (std::exception &exc) {
472             log(loglevel_t::ERROR, "Accepting control connection: ", exc.what());
473             close(newfd);
474         }
475     }
476 }
477
478 void open_control_socket(bool report_ro_failure) noexcept
479 {
480     if (! control_socket_open) {
481         const char * saddrname = control_socket_path;
482         size_t saddrname_len = strlen(saddrname);
483         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
484         
485         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
486         if (name == nullptr) {
487             log(loglevel_t::ERROR, "Opening control socket: out of memory");
488             return;
489         }
490
491         if (am_system_init) {
492             // Unlink any stale control socket file, but only if we are system init, since otherwise
493             // the 'stale' file may not be stale at all:
494             unlink(saddrname);
495         }
496
497         name->sun_family = AF_UNIX;
498         memcpy(name->sun_path, saddrname, saddrname_len + 1);
499
500         int sockfd = dinit_socket(AF_UNIX, SOCK_STREAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
501         if (sockfd == -1) {
502             log(loglevel_t::ERROR, "Error creating control socket: ", strerror(errno));
503             free(name);
504             return;
505         }
506
507         if (bind(sockfd, (struct sockaddr *) name, sockaddr_size) == -1) {
508             if (errno != EROFS || report_ro_failure) {
509                 log(loglevel_t::ERROR, "Error binding control socket: ", strerror(errno));
510             }
511             close(sockfd);
512             free(name);
513             return;
514         }
515         
516         free(name);
517
518         // No connections can be made until we listen, so it is fine to change the permissions now
519         // (and anyway there is no way to atomically create the socket and set permissions):
520         if (chmod(saddrname, S_IRUSR | S_IWUSR) == -1) {
521             log(loglevel_t::ERROR, "Error setting control socket permissions: ", strerror(errno));
522             close(sockfd);
523             return;
524         }
525
526         if (listen(sockfd, 10) == -1) {
527             log(loglevel_t::ERROR, "Error listening on control socket: ", strerror(errno));
528             close(sockfd);
529             return;
530         }
531
532         try {
533             control_socket_io.add_watch(event_loop, sockfd, dasynq::IN_EVENTS);
534             control_socket_open = true;
535         }
536         catch (std::exception &e)
537         {
538             log(loglevel_t::ERROR, "Could not setup I/O on control socket: ", e.what());
539             close(sockfd);
540         }
541     }
542 }
543
544 static void close_control_socket() noexcept
545 {
546     if (control_socket_open) {
547         int fd = control_socket_io.get_watched_fd();
548         control_socket_io.deregister(event_loop);
549         close(fd);
550         
551         // Unlink the socket:
552         unlink(control_socket_path);
553     }
554 }
555
556 void setup_external_log() noexcept
557 {
558     if (! external_log_open) {
559     
560         const char * saddrname = log_socket_path;
561         size_t saddrname_len = strlen(saddrname);
562         uint sockaddr_size = offsetof(struct sockaddr_un, sun_path) + saddrname_len + 1;
563         
564         struct sockaddr_un * name = static_cast<sockaddr_un *>(malloc(sockaddr_size));
565         if (name == nullptr) {
566             log(loglevel_t::ERROR, "Connecting to log socket: out of memory");
567             return;
568         }
569         
570         name->sun_family = AF_UNIX;
571         memcpy(name->sun_path, saddrname, saddrname_len + 1);
572         
573         int sockfd = dinit_socket(AF_UNIX, SOCK_DGRAM, 0, SOCK_NONBLOCK | SOCK_CLOEXEC);
574         if (sockfd == -1) {
575             log(loglevel_t::ERROR, "Error creating log socket: ", strerror(errno));
576             free(name);
577             return;
578         }
579         
580         if (connect(sockfd, (struct sockaddr *) name, sockaddr_size) == 0 || errno == EINPROGRESS) {
581             // For EINPROGRESS, connection is still being established; however, we can select on
582             // the file descriptor so we will be notified when it's ready. In other words we can
583             // basically use it anyway.
584             try {
585                 setup_main_log(sockfd);
586             }
587             catch (std::exception &e) {
588                 log(loglevel_t::ERROR, "Setting up log failed: ", e.what());
589                 close(sockfd);
590             }
591         }
592         else {
593             // Note if connect fails, we haven't warned at all, because the syslog server might not
594             // have started yet.
595             close(sockfd);
596         }
597         
598         free(name);
599     }
600 }
601
602 /* handle SIGINT signal (generated by Linux kernel when ctrl+alt+del pressed) */
603 static void sigint_reboot_cb(eventloop_t &eloop) noexcept
604 {
605     services->stop_all_services(shutdown_type_t::REBOOT);
606 }
607
608 /* handle SIGQUIT (if we are system init) */
609 static void sigquit_cb(eventloop_t &eloop) noexcept
610 {
611     // This performs an immediate shutdown, without service rollback.
612     close_control_socket();
613     execl("/sbin/shutdown", "/sbin/shutdown", "--system", (char *) 0);
614     log(loglevel_t::ERROR, "Error executing /sbin/shutdown: ", strerror(errno));
615     sync(); // since a hard poweroff might be required at this point...
616 }
617
618 /* handle SIGTERM/SIGQUIT(non-system-daemon) - stop all services and shut down */
619 static void sigterm_cb(eventloop_t &eloop) noexcept
620 {
621     services->stop_all_services();
622 }