X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=a1249dc093b47de9c172c571f200449c7fcb6fff;hb=8e70580bb07ae46dc0b0bf377de6333540668acc;hp=e2c06ae8b638123fe2df8d90908fb3f408ea2f75;hpb=7ed9f6cd785634dd093e1b1550c3c6183177abf6;p=elogind.git diff --git a/src/core/unit.c b/src/core/unit.c index e2c06ae8b..a1249dc09 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -48,6 +48,7 @@ #include "mkdir.h" #include "label.h" #include "fileio-label.h" +#include "bus-errors.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { [UNIT_SERVICE] = &service_vtable, @@ -1360,11 +1361,6 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) { ExecContext *ec = unit_get_exec_context(u); if (ec && exec_context_may_touch_console(ec)) { - /* XXX The counter may get out of sync if the admin edits - * TTY-related unit file properties and issues a daemon-reload - * while the unit is active. No big deal though, because - * it influences only the printing of boot/shutdown - * status messages. */ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) m->n_on_console--; else @@ -1517,7 +1513,8 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su /* Maybe we finished startup and are now ready for being * stopped because unneeded? */ - unit_check_unneeded(u); + if (u->manager->n_reloading <= 0) + unit_check_unneeded(u); unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); @@ -2451,6 +2448,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { job_free(j); return r; } + + if (j->state == JOB_RUNNING) + u->manager->n_running_jobs++; } else { /* legacy */ JobType type = job_type_from_string(v); @@ -2645,6 +2645,64 @@ int unit_kill(Unit *u, KillWho w, int signo, DBusError *error) { return UNIT_VTABLE(u)->kill(u, w, signo, error); } +int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t control_pid, DBusError *error) { + int r = 0; + + if (who == KILL_MAIN && main_pid <= 0) { + if (main_pid < 0) + dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type)); + else + dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill"); + return -ESRCH; + } + + if (who == KILL_CONTROL && control_pid <= 0) { + if (control_pid < 0) + dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type)); + else + dbus_set_error(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill"); + return -ESRCH; + } + + if (who == KILL_CONTROL || who == KILL_ALL) + if (control_pid > 0) + if (kill(control_pid, signo) < 0) + r = -errno; + + if (who == KILL_MAIN || who == KILL_ALL) + if (main_pid > 0) + if (kill(main_pid, signo) < 0) + r = -errno; + + if (who == KILL_ALL) { + _cleanup_set_free_ Set *pid_set = NULL; + int q; + + pid_set = set_new(trivial_hash_func, trivial_compare_func); + if (!pid_set) + return -ENOMEM; + + /* Exclude the control/main pid from being killed via the cgroup */ + if (control_pid > 0) { + q = set_put(pid_set, LONG_TO_PTR(control_pid)); + if (q < 0) + return q; + } + + if (main_pid > 0) { + q = set_put(pid_set, LONG_TO_PTR(main_pid)); + if (q < 0) + return q; + } + + q = cgroup_bonding_kill_list(u->cgroup_bondings, signo, false, false, pid_set, NULL); + if (q < 0 && q != -EAGAIN && q != -ESRCH && q != -ENOENT) + r = q; + } + + return r; +} + int unit_following_set(Unit *u, Set **s) { assert(u); assert(s);