X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=manager.c;h=8ee560c5543f0eb570857b12ed4fa7edb1445a96;hb=b19e7dc0104c8839835a90d7df20c2eeb631e07e;hp=b3123f2b1d2d57ac29f02b55acac9cec704a42af;hpb=6632c6023c5f90e15440231500d3431e869e4577;p=elogind.git diff --git a/manager.c b/manager.c index b3123f2b1..8ee560c55 100644 --- a/manager.c +++ b/manager.c @@ -15,12 +15,67 @@ #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,23 +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(sigaddset(&mask, SIGINT) == 0); - assert_se(sigaddset(&mask, SIGTERM) == 0); - assert_se(sigaddset(&mask, SIGWINCH) == 0); - assert_se(sigaddset(&mask, SIGHUP) == 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; @@ -1081,12 +1123,12 @@ int manager_loop(Manager *m) { 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; @@ -1094,12 +1136,12 @@ int manager_loop(Manager *m) { return -errno; } - for (i = 0; i < n; i++) { - if ((r = process_event(m, events + i, &quit)) < 0) - return r; + assert(n == 1); - if (quit) - return 0; - } + if ((r = process_event(m, &event, &quit)) < 0) + return r; + + if (quit) + return 0; } }