chiark / gitweb /
the systemd logger only matters in the abstract namespace
[elogind.git] / manager.c
index e9ae40ca7436bb0c642e0237f5410683cfb45196..8ee560c5543f0eb570857b12ed4fa7edb1445a96 100644 (file)
--- a/manager.c
+++ b/manager.c
 #include "macro.h"
 #include "strv.h"
 #include "log.h"
+#include "util.h"
 
-Manager* manager_new(void) {
-        Manager *m;
+static const char * const special_table[_SPECIAL_UNIT_MAX] = {
+        [SPECIAL_SYSLOG_SERVICE] = "syslog.service",
+        [SPECIAL_DBUS_SERVICE] = "messagebus.service",
+        [SPECIAL_LOGGER_SOCKET] = "systemd-logger.socket",
+        [SPECIAL_KBREQUEST_TARGET] = "kbrequest.target",
+        [SPECIAL_CTRL_ALT_DEL_TARGET] = "ctrl-alt-del.target"
+};
+
+static int manager_setup_signals(Manager *m) {
         sigset_t mask;
         struct epoll_event ev;
 
+        assert(m);
+
+        assert_se(reset_all_signal_handlers() == 0);
+
+        assert_se(sigemptyset(&mask) == 0);
+        assert_se(sigaddset(&mask, SIGCHLD) == 0);
+        assert_se(sigaddset(&mask, SIGINT) == 0);   /* Kernel sends us this on control-alt-del */
+        assert_se(sigaddset(&mask, SIGWINCH) == 0); /* Kernel sends us this on kbrequest (alt-arrowup) */
+        assert_se(sigaddset(&mask, SIGTERM) == 0);
+        assert_se(sigaddset(&mask, SIGHUP) == 0);
+        assert_se(sigaddset(&mask, SIGUSR1) == 0);
+        assert_se(sigaddset(&mask, SIGUSR2) == 0);
+        assert_se(sigaddset(&mask, SIGPIPE) == 0);
+        assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
+
+        m->signal_watch.type = WATCH_SIGNAL_FD;
+        if ((m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0)
+                return -errno;
+
+        zero(ev);
+        ev.events = EPOLLIN;
+        ev.data.ptr = &m->signal_watch;
+
+        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
+                return -errno;
+
+        return 0;
+}
+
+static int manager_load_special_units(Manager *m) {
+        SpecialUnit c;
+        int r;
+
+        assert(m);
+
+        /* Loads all 'special' units, so that we have easy access to them later */
+
+        for (c = 0; c < _SPECIAL_UNIT_MAX; c++)
+                if ((r = manager_load_unit(m, special_table[c], m->special_units+c)) < 0)
+                        return r;
+
+        return 0;
+};
+
+Manager* manager_new(void) {
+        Manager *m;
+
         if (!(m = new0(Manager, 1)))
                 return NULL;
 
@@ -41,19 +96,10 @@ Manager* manager_new(void) {
         if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0)
                 goto fail;
 
-        assert_se(sigemptyset(&mask) == 0);
-        assert_se(sigaddset(&mask, SIGCHLD) == 0);
-        assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0);
-
-        m->signal_watch.type = WATCH_SIGNAL_FD;
-        if ((m->signal_watch.fd = signalfd(-1, &mask, SFD_NONBLOCK|SFD_CLOEXEC)) < 0)
+        if (manager_setup_signals(m) < 0)
                 goto fail;
 
-        zero(ev);
-        ev.events = EPOLLIN;
-        ev.data.ptr = &m->signal_watch;
-
-        if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0)
+        if (manager_load_special_units(m) < 0)
                 goto fail;
 
         return m;
@@ -977,7 +1023,7 @@ static int manager_dispatch_sigchld(Manager *m) {
         return 0;
 }
 
-static int manager_process_signal_fd(Manager *m) {
+static int manager_process_signal_fd(Manager *m, bool *quit) {
         ssize_t n;
         struct signalfd_siginfo sfsi;
         bool sigchld = false;
@@ -996,8 +1042,20 @@ static int manager_process_signal_fd(Manager *m) {
                         return -errno;
                 }
 
-                if (sfsi.ssi_signo == SIGCHLD)
+                switch (sfsi.ssi_signo) {
+
+                case SIGCHLD:
                         sigchld = true;
+                        break;
+
+                case SIGINT:
+                case SIGTERM:
+                        *quit = true;
+                        return 0;
+
+                default:
+                        log_info("Got unhandled signal <%s>.", strsignal(sfsi.ssi_signo));
+                }
         }
 
         if (sigchld)
@@ -1006,7 +1064,7 @@ static int manager_process_signal_fd(Manager *m) {
         return 0;
 }
 
-static int process_event(Manager *m, struct epoll_event *ev) {
+static int process_event(Manager *m, struct epoll_event *ev, bool *quit) {
         int r;
         Watch *w;
 
@@ -1023,7 +1081,7 @@ static int process_event(Manager *m, struct epoll_event *ev) {
                 if (ev->events != POLLIN)
                         return -EINVAL;
 
-                if ((r = manager_process_signal_fd(m)) < 0)
+                if ((r = manager_process_signal_fd(m, quit)) < 0)
                         return r;
 
                 break;
@@ -1060,16 +1118,17 @@ static int process_event(Manager *m, struct epoll_event *ev) {
 
 int manager_loop(Manager *m) {
         int r;
+        bool quit = false;
 
         assert(m);
 
         for (;;) {
-                struct epoll_event events[32];
-                int n, i;
+                struct epoll_event event;
+                int n;
 
                 manager_dispatch_run_queue(m);
 
-                if ((n = epoll_wait(m->epoll_fd, events, ELEMENTSOF(events), -1)) < 0) {
+                if ((n = epoll_wait(m->epoll_fd, &event, 1, -1)) < 0) {
 
                         if (errno == -EINTR)
                                 continue;
@@ -1077,8 +1136,12 @@ int manager_loop(Manager *m) {
                         return -errno;
                 }
 
-                for (i = 0; i < n; i++)
-                        if ((r = process_event(m, events + i)) < 0)
-                                return r;
+                assert(n == 1);
+
+                if ((r = process_event(m, &event, &quit)) < 0)
+                        return r;
+
+                if (quit)
+                        return 0;
         }
 }