X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fmanager.c;h=f9763c838a2faab722fd6b0720579818931d31b7;hp=97d05b52c36950cffcfa1b7508cf2866dbe3b3fa;hb=e6b3f00f6675475b770d3693498b224f232b0d1c;hpb=8c47c7325fa1ab72febf807f8831ff24c75fbf45 diff --git a/src/manager.c b/src/manager.c index 97d05b52c..f9763c838 100644 --- a/src/manager.c +++ b/src/manager.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -53,6 +52,7 @@ #include "dbus-job.h" #include "missing.h" #include "path-lookup.h" +#include "special.h" /* As soon as 16 units are in our GC queue, make sure to run a gc sweep */ #define GC_QUEUE_ENTRIES_MAX 16 @@ -69,7 +69,6 @@ static int manager_setup_notify(Manager *m) { struct sockaddr_un un; } sa; struct epoll_event ev; - char *ne[2], **t; int one = 1; assert(m); @@ -105,19 +104,9 @@ static int manager_setup_notify(Manager *m) { if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->notify_watch.fd, &ev) < 0) return -errno; - if (asprintf(&ne[0], "NOTIFY_SOCKET=@%s", sa.un.sun_path+1) < 0) + if (!(m->notify_socket = strdup(sa.un.sun_path+1))) return -ENOMEM; - ne[1] = NULL; - t = strv_env_merge(m->environment, ne, NULL); - free(ne[0]); - - if (!t) - return -ENOMEM; - - strv_free(m->environment); - m->environment = t; - return 0; } @@ -157,14 +146,23 @@ static int manager_setup_signals(Manager *m) { assert_se(sigaction(SIGCHLD, &sa, NULL) == 0); assert_se(sigemptyset(&mask) == 0); - assert_se(sigaddset(&mask, SIGCHLD) == 0); - 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, 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, SIGPWR) == 0); /* Some kernel drivers and upsd send us this on power failure */ + + sigset_add_many(&mask, + SIGCHLD, /* Child died */ + SIGTERM, /* Reexecute daemon */ + SIGHUP, /* Reload configuration */ + SIGUSR1, /* systemd/upstart: reconnect to D-Bus */ + SIGUSR2, /* systemd: dump status */ + SIGINT, /* Kernel sends us this on control-alt-del */ + SIGWINCH, /* Kernel sends us this on kbrequest (alt-arrowup) */ + SIGPWR, /* Some kernel drivers and upsd send us this on power failure */ + SIGRTMIN+0, /* systemd: start default.target */ + SIGRTMIN+1, /* systemd: start rescue.target */ + SIGRTMIN+2, /* systemd: isolate emergency.target */ + SIGRTMIN+3, /* systemd: start halt.target */ + SIGRTMIN+4, /* systemd: start poweroff.target */ + SIGRTMIN+5, /* systemd: start reboot.target */ + -1); assert_se(sigprocmask(SIG_SETMASK, &mask, NULL) == 0); m->signal_watch.type = WATCH_SIGNAL; @@ -178,7 +176,7 @@ 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) + if (m->running_as == MANAGER_SYSTEM) return enable_special_signals(m); return 0; @@ -187,6 +185,7 @@ static int manager_setup_signals(Manager *m) { int manager_new(ManagerRunningAs running_as, bool confirm_spawn, Manager **_m) { Manager *m; int r = -ENOMEM; + char *p; assert(_m); assert(running_as >= 0); @@ -201,6 +200,7 @@ int manager_new(ManagerRunningAs running_as, bool confirm_spawn, Manager **_m) { m->confirm_spawn = confirm_spawn; m->name_data_slot = -1; m->exit_code = _MANAGER_EXIT_CODE_INVALID; + m->pin_cgroupfs_fd = -1; m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = -1; m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */ @@ -242,10 +242,17 @@ int manager_new(ManagerRunningAs running_as, bool confirm_spawn, Manager **_m) { goto fail; /* Try to connect to the busses, if possible. */ - if ((r = bus_init_system(m)) < 0 || - (r = bus_init_api(m)) < 0) + if ((r = bus_init(m)) < 0) goto fail; + if (asprintf(&p, "%s/%s", m->cgroup_mount_point, m->cgroup_hierarchy) < 0) { + r = -ENOMEM; + goto fail; + } + + m->pin_cgroupfs_fd = open(p, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK); + free(p); + *_m = m; return 0; @@ -263,7 +270,7 @@ static unsigned manager_dispatch_cleanup_queue(Manager *m) { while ((meta = m->cleanup_queue)) { assert(meta->in_cleanup_queue); - unit_free(UNIT(meta)); + unit_free((Unit*) meta); n++; } @@ -353,7 +360,7 @@ static unsigned manager_dispatch_gc_queue(Manager *m) { while ((meta = m->gc_queue)) { assert(meta->in_gc_queue); - unit_gc_sweep(UNIT(meta), gc_marker); + unit_gc_sweep((Unit*) meta, gc_marker); LIST_REMOVE(Meta, gc_queue, m->gc_queue, meta); meta->in_gc_queue = false; @@ -364,7 +371,7 @@ static unsigned manager_dispatch_gc_queue(Manager *m) { meta->gc_marker == gc_marker + GC_OFFSET_UNSURE) { log_debug("Collecting %s", meta->id); meta->gc_marker = gc_marker + GC_OFFSET_BAD; - unit_add_to_cleanup_queue(UNIT(meta)); + unit_add_to_cleanup_queue((Unit*) meta); } } @@ -413,10 +420,10 @@ void manager_free(Manager *m) { /* If we reexecute ourselves, we keep the root cgroup * around */ - manager_shutdown_cgroup(m, m->exit_code != MANAGER_REEXECUTE); + if (m->exit_code != MANAGER_REEXECUTE) + manager_shutdown_cgroup(m); - bus_done_api(m); - bus_done_system(m); + bus_done(m); hashmap_free(m->units); hashmap_free(m->jobs); @@ -431,14 +438,20 @@ void manager_free(Manager *m) { if (m->notify_watch.fd >= 0) close_nointr_nofail(m->notify_watch.fd); + free(m->notify_socket); + lookup_paths_free(&m->lookup_paths); strv_free(m->environment); free(m->cgroup_controller); free(m->cgroup_hierarchy); + free(m->cgroup_mount_point); hashmap_free(m->cgroup_bondings); + if (m->pin_cgroupfs_fd >= 0) + close_nointr_nofail(m->pin_cgroupfs_fd); + free(m); } @@ -1426,7 +1439,7 @@ unsigned manager_dispatch_load_queue(Manager *m) { while ((meta = m->load_queue)) { assert(meta->in_load_queue); - unit_load(UNIT(meta)); + unit_load((Unit*) meta); n++; } @@ -1572,7 +1585,7 @@ unsigned manager_dispatch_dbus_queue(Manager *m) { while ((meta = m->dbus_unit_queue)) { assert(meta->in_dbus_queue); - bus_unit_send_change_signal(UNIT(meta)); + bus_unit_send_change_signal((Unit*) meta); n++; } @@ -1641,14 +1654,15 @@ static int manager_process_notify_fd(Manager *m) { continue; } - char_array_0(buf); + assert((size_t) n < sizeof(buf)); + buf[n] = 0; if (!(tags = strv_split(buf, "\n\r"))) return -ENOMEM; log_debug("Got notification message for unit %s", u->meta.id); if (UNIT_VTABLE(u)->notify_message) - UNIT_VTABLE(u)->notify_message(u, tags); + UNIT_VTABLE(u)->notify_message(u, ucred->pid, tags); strv_free(tags); } @@ -1687,7 +1701,7 @@ static int manager_dispatch_sigchld(Manager *m) { char *name = NULL; get_process_name(si.si_pid, &name); - log_debug("Got SIGCHLD for process %llu (%s)", (unsigned long long) si.si_pid, strna(name)); + log_debug("Got SIGCHLD for process %lu (%s)", (unsigned long) si.si_pid, strna(name)); free(name); } @@ -1713,8 +1727,8 @@ static int manager_dispatch_sigchld(Manager *m) { if (si.si_code != CLD_EXITED && si.si_code != CLD_KILLED && si.si_code != CLD_DUMPED) continue; - log_debug("Child %llu died (code=%s, status=%i/%s)", - (long long unsigned) si.si_pid, + log_debug("Child %lu died (code=%s, status=%i/%s)", + (long unsigned) si.si_pid, sigchld_code_to_string(si.si_code), si.si_status, strna(si.si_code == CLD_EXITED ? exit_status_to_string(si.si_status) : strsignal(si.si_status))); @@ -1731,10 +1745,10 @@ static int manager_dispatch_sigchld(Manager *m) { return 0; } -static int manager_start_target(Manager *m, const char *name) { +static int manager_start_target(Manager *m, const char *name, JobMode mode) { int r; - if ((r = manager_add_job_by_name(m, JOB_START, name, JOB_REPLACE, true, NULL)) < 0) + if ((r = manager_add_job_by_name(m, JOB_START, name, mode, true, NULL)) < 0) log_error("Failed to enqueue %s job: %s", name, strerror(-r)); return r; @@ -1766,7 +1780,7 @@ static int manager_process_signal_fd(Manager *m) { break; case SIGTERM: - if (m->running_as == MANAGER_INIT) { + if (m->running_as == MANAGER_SYSTEM) { /* This is for compatibility with the * original sysvinit */ m->exit_code = MANAGER_REEXECUTE; @@ -1776,13 +1790,13 @@ static int manager_process_signal_fd(Manager *m) { /* Fall through */ case SIGINT: - if (m->running_as == MANAGER_INIT) { - manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET); + if (m->running_as == MANAGER_SYSTEM) { + manager_start_target(m, SPECIAL_CTRL_ALT_DEL_TARGET, JOB_REPLACE); break; } /* Run the exit target if there is one, if not, just exit. */ - if (manager_start_target(m, SPECIAL_EXIT_SERVICE) < 0) { + if (manager_start_target(m, SPECIAL_EXIT_SERVICE, JOB_REPLACE) < 0) { m->exit_code = MANAGER_EXIT; return 0; } @@ -1790,15 +1804,15 @@ static int manager_process_signal_fd(Manager *m) { break; case SIGWINCH: - if (m->running_as == MANAGER_INIT) - manager_start_target(m, SPECIAL_KBREQUEST_TARGET); + if (m->running_as == MANAGER_SYSTEM) + manager_start_target(m, SPECIAL_KBREQUEST_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; case SIGPWR: - if (m->running_as == MANAGER_INIT) - manager_start_target(m, SPECIAL_SIGPWR_TARGET); + if (m->running_as == MANAGER_SYSTEM) + manager_start_target(m, SPECIAL_SIGPWR_TARGET, JOB_REPLACE); /* This is a nop on non-init */ break; @@ -1810,13 +1824,12 @@ static int manager_process_signal_fd(Manager *m) { if (!u || UNIT_IS_ACTIVE_OR_RELOADING(unit_active_state(u))) { log_info("Trying to reconnect to bus..."); - bus_init_system(m); - bus_init_api(m); + bus_init(m); } if (!u || !UNIT_IS_ACTIVE_OR_ACTIVATING(unit_active_state(u))) { log_info("Loading D-Bus service..."); - manager_start_target(m, SPECIAL_DBUS_SERVICE); + manager_start_target(m, SPECIAL_DBUS_SERVICE, JOB_REPLACE); } break; @@ -1853,9 +1866,26 @@ static int manager_process_signal_fd(Manager *m) { m->exit_code = MANAGER_RELOAD; break; - default: + default: { + static const char * const table[] = { + [0] = SPECIAL_DEFAULT_TARGET, + [1] = SPECIAL_RESCUE_TARGET, + [2] = SPECIAL_EMERGENCY_SERVICE, + [3] = SPECIAL_HALT_TARGET, + [4] = SPECIAL_POWEROFF_TARGET, + [5] = SPECIAL_REBOOT_TARGET + }; + + if ((int) sfsi.ssi_signo >= SIGRTMIN+0 && + (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(table)) { + manager_start_target(m, table[sfsi.ssi_signo - SIGRTMIN], + (sfsi.ssi_signo == 1 || sfsi.ssi_signo == 2) ? JOB_ISOLATE : JOB_REPLACE); + break; + } + log_info("Got unhandled signal <%s>.", strsignal(sfsi.ssi_signo)); } + } } if (sigchld) @@ -2075,7 +2105,7 @@ void manager_write_utmp_reboot(Manager *m) { if (m->utmp_reboot_written) return; - if (m->running_as != MANAGER_INIT) + if (m->running_as != MANAGER_SYSTEM) return; if (!manager_utmp_good(m)) @@ -2101,7 +2131,7 @@ void manager_write_utmp_runlevel(Manager *m, Unit *u) { if (u->meta.type != UNIT_TARGET) return; - if (m->running_as != MANAGER_INIT) + if (m->running_as != MANAGER_SYSTEM) return; if (!manager_utmp_good(m)) @@ -2307,7 +2337,6 @@ finish: } static const char* const manager_running_as_table[_MANAGER_RUNNING_AS_MAX] = { - [MANAGER_INIT] = "init", [MANAGER_SYSTEM] = "system", [MANAGER_SESSION] = "session" };