X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=20b139d31be6446aeb2090332a952337d6843988;hp=05470739d289a20e7023c0f28fa93d9cd28cbba8;hb=f1660f96f59dad860d39f148c3a747050d112763;hpb=f513e420c8b1a1d4c13092cd378f048b69793497 diff --git a/src/core/unit.c b/src/core/unit.c index 05470739d..20b139d31 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -328,7 +328,8 @@ void unit_add_to_dbus_queue(Unit *u) { return; /* Shortcut things if nobody cares */ - if (set_isempty(u->manager->subscribed)) { + if (sd_bus_track_count(u->manager->subscribed) <= 0 && + set_isempty(u->manager->private_buses)) { u->sent_dbus_new_signal = true; return; } @@ -470,6 +471,8 @@ void unit_free(Unit *u) { free(u->cgroup_path); } + set_remove(u->manager->failed_units, u); + free(u->description); strv_free(u->documentation); free(u->fragment_path); @@ -1506,6 +1509,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su m = u->manager; + /* Update timestamps for state changes */ if (m->n_reloading <= 0) { dual_timestamp ts; @@ -1522,11 +1526,18 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su u->active_exit_timestamp = ts; } + /* Keep track of failed of units */ + if (ns == UNIT_FAILED && os != UNIT_FAILED) + set_put(u->manager->failed_units, u); + else if (os == UNIT_FAILED && ns != UNIT_FAILED) + set_remove(u->manager->failed_units, u); + + /* Make sure the cgroup is always removed when we become inactive */ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) unit_destroy_cgroup(u); /* Note that this doesn't apply to RemainAfterExit services exiting - * sucessfully, since there's no change of state in that case. Which is + * successfully, since there's no change of state in that case. Which is * why it is handled in service_set_state() */ if (UNIT_IS_INACTIVE_OR_FAILED(os) != UNIT_IS_INACTIVE_OR_FAILED(ns)) { ExecContext *ec; @@ -1703,11 +1714,11 @@ int unit_watch_pid(Unit *u, pid_t pid) { /* Watch a specific PID. We only support one or two units * watching each PID for now, not more. */ - r = hashmap_ensure_allocated(&u->manager->watch_pids1, trivial_hash_func, trivial_compare_func); + r = set_ensure_allocated(&u->pids, trivial_hash_func, trivial_compare_func); if (r < 0) return r; - r = set_ensure_allocated(&u->pids, trivial_hash_func, trivial_compare_func); + r = hashmap_ensure_allocated(&u->manager->watch_pids1, trivial_hash_func, trivial_compare_func); if (r < 0) return r; @@ -1736,7 +1747,17 @@ void unit_unwatch_pid(Unit *u, pid_t pid) { set_remove(u->pids, LONG_TO_PTR(pid)); } -static int watch_pids_in_path(Unit *u, const char *path) { +void unit_unwatch_all_pids(Unit *u) { + assert(u); + + while (!set_isempty(u->pids)) + unit_unwatch_pid(u, PTR_TO_LONG(set_first(u->pids))); + + set_free(u->pids); + u->pids = NULL; +} + +static int unit_watch_pids_in_path(Unit *u, const char *path) { _cleanup_closedir_ DIR *d = NULL; _cleanup_fclose_ FILE *f = NULL; int ret = 0, r; @@ -1774,7 +1795,7 @@ static int watch_pids_in_path(Unit *u, const char *path) { if (!p) return -ENOMEM; - r = watch_pids_in_path(u, p); + r = unit_watch_pids_in_path(u, p); if (r < 0 && ret >= 0) ret = r; } @@ -1787,31 +1808,15 @@ static int watch_pids_in_path(Unit *u, const char *path) { return ret; } - int unit_watch_all_pids(Unit *u) { assert(u); - if (!u->cgroup_path) - return -ENOENT; - /* Adds all PIDs from our cgroup to the set of PIDs we watch */ - return watch_pids_in_path(u, u->cgroup_path); -} - -void unit_unwatch_all_pids(Unit *u) { - Iterator i; - void *e; - - assert(u); - - SET_FOREACH(e, u->pids, i) { - hashmap_remove_value(u->manager->watch_pids1, e, u); - hashmap_remove_value(u->manager->watch_pids2, e, u); - } + if (!u->cgroup_path) + return -ENOENT; - set_free(u->pids); - u->pids = NULL; + return unit_watch_pids_in_path(u, u->cgroup_path); } void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) { @@ -1829,7 +1834,7 @@ void unit_tidy_watch_pids(Unit *u, pid_t except1, pid_t except2) { continue; if (!pid_is_unwaited(pid)) - set_remove(u->pids, e); + unit_unwatch_pid(u, pid); } } @@ -2802,7 +2807,7 @@ int unit_exec_context_patch_defaults(Unit *u, ExecContext *c) { * _after_ the rest of the settings have been initialized */ /* This only copies in the ones that need memory */ - for (i = 0; i < RLIMIT_NLIMITS; i++) + for (i = 0; i < _RLIMIT_MAX; i++) if (u->manager->rlimit[i] && !c->rlimit[i]) { c->rlimit[i] = newdup(struct rlimit, u->manager->rlimit[i], 1); if (!c->rlimit[i]) @@ -2825,6 +2830,9 @@ int unit_exec_context_patch_defaults(Unit *u, ExecContext *c) { !set_isempty(c->address_families))) c->no_new_privileges = true; + if (c->private_devices) + c->capability_bounding_set_drop |= (uint64_t) 1ULL << (uint64_t) CAP_MKNOD; + return 0; } @@ -3180,11 +3188,9 @@ int unit_require_mounts_for(Unit *u, const char *path) { return 0; } - r = strv_push(&u->requires_mounts_for, p); - if (r < 0) { - free(p); + r = strv_consume(&u->requires_mounts_for, p); + if (r < 0) return r; - } PATH_FOREACH_PREFIX_MORE(prefix, p) { Set *x; @@ -3285,9 +3291,9 @@ static const char* const unit_dependency_table[_UNIT_DEPENDENCY_MAX] = { [UNIT_TRIGGERED_BY] = "TriggeredBy", [UNIT_PROPAGATES_RELOAD_TO] = "PropagatesReloadTo", [UNIT_RELOAD_PROPAGATED_FROM] = "ReloadPropagatedFrom", + [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf", [UNIT_REFERENCES] = "References", [UNIT_REFERENCED_BY] = "ReferencedBy", - [UNIT_JOINS_NAMESPACE_OF] = "JoinsNamespaceOf", }; DEFINE_STRING_TABLE_LOOKUP(unit_dependency, UnitDependency);