X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=manager.c;h=e9bd3669041ceec88a56f43cf9a121e6541cd53b;hb=24e61ac49db6add10ffa448f42202245fb883b96;hp=bec13988873b3386b4d58061d3fce15f9e0917f0;hpb=036643a247c659db8e1b3df1778d51553a816ec9;p=elogind.git diff --git a/manager.c b/manager.c index bec139888..e9bd36690 100644 --- a/manager.c +++ b/manager.c @@ -28,6 +28,10 @@ #include #include #include +#include +#include +#include +#include #include "manager.h" #include "hashmap.h" @@ -36,6 +40,8 @@ #include "log.h" #include "util.h" #include "ratelimit.h" +#include "cgroup.h" +#include "mount-setup.h" static int manager_setup_signals(Manager *m) { sigset_t mask; @@ -54,6 +60,8 @@ static int manager_setup_signals(Manager *m) { assert_se(sigaddset(&mask, SIGUSR1) == 0); assert_se(sigaddset(&mask, SIGUSR2) == 0); assert_se(sigaddset(&mask, SIGPIPE) == 0); + assert_se(sigaddset(&mask, SIGPWR) == 0); + assert_se(sigaddset(&mask, SIGTTIN) == 0); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); m->signal_watch.type = WATCH_SIGNAL; @@ -67,6 +75,16 @@ static int manager_setup_signals(Manager *m) { if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->signal_watch.fd, &ev) < 0) return -errno; + if (m->running_as == MANAGER_INIT) { + /* Enable that we get SIGINT on control-alt-del */ + if (reboot(RB_DISABLE_CAD) < 0) + log_warning("Failed to enable ctrl-alt-del handling: %s", strerror(errno)); + + /* Enable that we get SIGWINCH on kbrequest */ + if (ioctl(0, KDSIGACCEPT, SIGWINCH) < 0) + log_warning("Failed to enable kbrequest handling: %s", strerror(errno)); + } + return 0; } @@ -200,8 +218,7 @@ static int manager_find_paths(Manager *m) { return -ENOMEM; } - /* FIXME: This should probably look for MANAGER_INIT, and exclude MANAGER_SYSTEM */ - if (m->running_as != MANAGER_SESSION) { + if (m->running_as == MANAGER_INIT) { /* /etc/init.d/ compativility does not matter to users */ if ((e = getenv("SYSTEMD_SYSVINIT_PATH"))) @@ -240,27 +257,18 @@ static int manager_find_paths(Manager *m) { return 0; } -Manager* manager_new(void) { +int manager_new(Manager **_m) { Manager *m; + int r = -ENOMEM; - if (!(m = new0(Manager, 1))) - return NULL; + assert(_m); - if (getpid() == 1) - m->running_as = MANAGER_INIT; - else if (getuid() == 0) - m->running_as = MANAGER_SYSTEM; - else - m->running_as = MANAGER_SESSION; - - log_debug("systemd running in %s mode.", manager_running_as_to_string(m->running_as)); + if (!(m = new0(Manager, 1))) + return -ENOMEM; m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = -1; m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ - if (manager_find_paths(m) < 0) - goto fail; - if (!(m->units = hashmap_new(string_hash_func, string_compare_func))) goto fail; @@ -273,21 +281,49 @@ Manager* manager_new(void) { if (!(m->watch_pids = hashmap_new(trivial_hash_func, trivial_compare_func))) goto fail; + if (!(m->cgroup_bondings = hashmap_new(string_hash_func, string_compare_func))) + goto fail; + if ((m->epoll_fd = epoll_create1(EPOLL_CLOEXEC)) < 0) goto fail; - if (manager_setup_signals(m) < 0) + if (getpid() == 1) + m->running_as = MANAGER_INIT; + else if (getuid() == 0) + m->running_as = MANAGER_SYSTEM; + else + m->running_as = MANAGER_SESSION; + + log_debug("systemd running in %s mode.", manager_running_as_to_string(m->running_as)); + + if ((r = manager_find_paths(m)) < 0) + goto fail; + + if (chdir("/") < 0) + log_warning("Failed to chdir to /: %s", strerror(errno)); + + /* Become a session leader if we aren't one yet. */ + setsid(); + + if ((r = manager_setup_signals(m)) < 0) + goto fail; + + if ((r = mount_setup()) < 0) + goto fail; + + if ((r = manager_setup_cgroup(m)) < 0) goto fail; /* FIXME: this should be called only when the D-Bus bus daemon is running */ - if (bus_init(m) < 0) + if ((r = bus_init(m)) < 0) goto fail; - return m; + *_m = m; + return 0; fail: manager_free(m); - return NULL; + return r; } void manager_free(Manager *m) { @@ -307,6 +343,8 @@ void manager_free(Manager *m) { if (unit_vtable[c]->shutdown) unit_vtable[c]->shutdown(m); + manager_shutdown_cgroup(m); + bus_done(m); hashmap_free(m->units); @@ -322,6 +360,12 @@ void manager_free(Manager *m) { strv_free(m->unit_path); strv_free(m->sysvinit_path); + free(m->cgroup_controller); + free(m->cgroup_hierarchy); + + assert(hashmap_isempty(m->cgroup_bondings)); + hashmap_free(m->cgroup_bondings); + free(m); } @@ -1184,7 +1228,7 @@ int manager_load_unit(Manager *m, const char *path, Unit **_ret) { return -ENOMEM; if (is_path(path)) { - if (!(ret->meta.load_path = strdup(path))) { + if (!(ret->meta.fragment_path = strdup(path))) { unit_free(ret); return -ENOMEM; } @@ -1353,8 +1397,40 @@ static int manager_process_signal_fd(Manager *m, bool *quit) { case SIGINT: case SIGTERM: - *quit = true; - return 0; + + if (m->running_as != MANAGER_INIT) { + *quit = true; + return 0; + + } else { + Unit *target; + int r; + + if ((r = manager_load_unit(m, SPECIAL_CTRL_ALT_DEL_TARGET, &target)) < 0) + log_error("Failed to load ctrl-alt-del target: %s", strerror(-r)); + else if ((r = manager_add_job(m, JOB_START, target, JOB_REPLACE, true, NULL)) < 0) + log_error("Failed to enqueue ctrl-alt-del job: %s", strerror(-r)); + + break; + } + + case SIGWINCH: + + if (m->running_as == MANAGER_INIT) { + Unit *target; + int r; + + if ((r = manager_load_unit(m, SPECIAL_KBREQUEST_TARGET, &target)) < 0) + log_error("Failed to load kbrequest target: %s", strerror(-r)); + else if ((r = manager_add_job(m, JOB_START, target, JOB_REPLACE, true, NULL)) < 0) + log_error("Failed to enqueue kbrequest job: %s", strerror(-r)); + + break; + } + + /* This is a nop on non-init systemd's */ + + break; default: log_info("Got unhandled signal <%s>.", strsignal(sfsi.ssi_signo));