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=016b1e3d869d846b29806e1be9f758c8529f249d;hb=f1660f96f59dad860d39f148c3a747050d112763;hpb=db57f3c6d11864f4227bb6734a0d509695a32a7d diff --git a/src/core/unit.c b/src/core/unit.c index 016b1e3d8..20b139d31 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -259,9 +259,6 @@ int unit_set_description(Unit *u, const char *description) { bool unit_check_gc(Unit *u) { assert(u); - if (u->load_state == UNIT_STUB) - return true; - if (UNIT_VTABLE(u)->no_gc) return true; @@ -331,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; } @@ -473,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); @@ -1140,8 +1140,6 @@ _pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, Job return NULL; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" static void unit_status_print_starting_stopping(Unit *u, JobType t) { const char *format; @@ -1154,12 +1152,11 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) { if (!format) return; + DISABLE_WARNING_FORMAT_NONLITERAL; unit_status_printf(u, "", format); + REENABLE_WARNING; } -#pragma GCC diagnostic pop -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { const char *format; char buf[LINE_MAX]; @@ -1179,8 +1176,10 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { if (!format) return; + DISABLE_WARNING_FORMAT_NONLITERAL; snprintf(buf, sizeof(buf), format, unit_description(u)); char_array_0(buf); + REENABLE_WARNING; mid = t == JOB_START ? SD_MESSAGE_UNIT_STARTING : t == JOB_STOP ? SD_MESSAGE_UNIT_STOPPING : @@ -1192,7 +1191,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { "MESSAGE=%s", buf, NULL); } -#pragma GCC diagnostic pop /* Errors: * -EBADR: This unit type does not support starting. @@ -1511,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; @@ -1527,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; @@ -1708,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; @@ -1741,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; @@ -1779,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; } @@ -1792,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) { @@ -1834,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); } } @@ -2525,12 +2525,11 @@ int unit_coldplug(Unit *u) { return 0; } -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) { + DISABLE_WARNING_FORMAT_NONLITERAL; manager_status_printf(u->manager, false, status, unit_status_msg_format, unit_description(u)); + REENABLE_WARNING; } -#pragma GCC diagnostic pop bool unit_need_daemon_reload(Unit *u) { _cleanup_strv_free_ char **t = NULL; @@ -2783,15 +2782,32 @@ void unit_ref_unset(UnitRef *ref) { ref->unit = NULL; } -int unit_exec_context_defaults(Unit *u, ExecContext *c) { +int unit_cgroup_context_init_defaults(Unit *u, CGroupContext *c) { + assert(u); + assert(c); + + /* Copy in the manager defaults into the cgroup context, + * _before_ the rest of the settings have been initialized */ + + c->cpu_accounting = u->manager->default_cpu_accounting; + c->blockio_accounting = u->manager->default_blockio_accounting; + c->memory_accounting = u->manager->default_memory_accounting; + + return 0; +} + +int unit_exec_context_patch_defaults(Unit *u, ExecContext *c) { unsigned i; int r; assert(u); assert(c); + /* Patch in the manager defaults into the exec context, + * _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]) @@ -2806,6 +2822,17 @@ int unit_exec_context_defaults(Unit *u, ExecContext *c) { return r; } + if (u->manager->running_as == SYSTEMD_USER && + (c->syscall_whitelist || + !set_isempty(c->syscall_filter) || + !set_isempty(c->syscall_archs) || + c->address_families_whitelist || + !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; } @@ -3161,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; @@ -3266,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);