X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Funit.c;h=875befa0a200e5ce83771316be36c8561009e8be;hp=489ea1e502945a624b2e6d587023fcbd852f2e0d;hb=5bd4b173605142c7be493aa4d958ebaef21f421d;hpb=127d5fd1563a74411aaceeadd251f98fd52216d7 diff --git a/src/core/unit.c b/src/core/unit.c index 489ea1e50..875befa0a 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -19,12 +19,8 @@ along with systemd; If not, see . ***/ -#include #include #include -#include -#include -#include #include #include #include @@ -45,12 +41,10 @@ #include "cgroup-util.h" #include "missing.h" #include "mkdir.h" -#include "label.h" #include "fileio-label.h" -#include "bus-errors.h" +#include "bus-common-errors.h" #include "dbus.h" #include "execute.h" -#include "virt.h" #include "dropin.h" const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX] = { @@ -92,6 +86,7 @@ Unit *unit_new(Manager *m, size_t size) { u->deserialized_job = _JOB_TYPE_INVALID; u->default_dependencies = true; u->unit_file_state = _UNIT_FILE_STATE_INVALID; + u->unit_file_preset = -1; u->on_failure_job_mode = JOB_REPLACE; return u; @@ -277,21 +272,32 @@ int unit_set_description(Unit *u, const char *description) { } bool unit_check_gc(Unit *u) { + UnitActiveState state; assert(u); - if (UNIT_VTABLE(u)->no_gc) + if (u->job) return true; - if (u->no_gc) + if (u->nop_job) return true; - if (u->job) + state = unit_active_state(u); + + /* If the unit is inactive and failed and no job is queued for + * it, then release its runtime resources */ + if (UNIT_IS_INACTIVE_OR_FAILED(state) && + UNIT_VTABLE(u)->release_resources) + UNIT_VTABLE(u)->release_resources(u); + + /* But we keep the unit object around for longer when it is + * referenced or configured to not be gc'ed */ + if (state != UNIT_INACTIVE) return true; - if (u->nop_job) + if (UNIT_VTABLE(u)->no_gc) return true; - if (unit_active_state(u) != UNIT_INACTIVE) + if (u->no_gc) return true; if (u->refs) @@ -527,6 +533,7 @@ void unit_free(Unit *u) { unit_unwatch_all_pids(u); condition_free_list(u->conditions); + condition_free_list(u->asserts); unit_ref_unset(&u->slice); @@ -607,7 +614,7 @@ static int reserve_dependencies(Unit *u, Unit *other, UnitDependency d) { /* * If u does not have this dependency set allocated, there is no need - * to reserve anything. In that case other's set will be transfered + * to reserve anything. In that case other's set will be transferred * as a whole to u by complete_move(). */ if (!u->dependencies[d]) @@ -855,7 +862,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { assert(u->type >= 0); prefix = strempty(prefix); - prefix2 = strappenda(prefix, "\t"); + prefix2 = strjoina(prefix, "\t"); fprintf(f, "%s-> Unit %s:\n" @@ -929,7 +936,8 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { if (u->job_timeout_reboot_arg) fprintf(f, "%s\tJob Timeout Reboot Argument: %s\n", prefix, u->job_timeout_reboot_arg); - condition_dump_list(u->conditions, f, prefix); + condition_dump_list(u->conditions, f, prefix, condition_type_to_string); + condition_dump_list(u->asserts, f, prefix, assert_type_to_string); if (dual_timestamp_is_set(&u->condition_timestamp)) fprintf(f, @@ -938,6 +946,13 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->condition_timestamp.realtime)), prefix, yes_no(u->condition_result)); + if (dual_timestamp_is_set(&u->assert_timestamp)) + fprintf(f, + "%s\tAssert Timestamp: %s\n" + "%s\tAssert Result: %s\n", + prefix, strna(format_timestamp(timestamp1, sizeof(timestamp1), u->assert_timestamp.realtime)), + prefix, yes_no(u->assert_result)); + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) { Unit *other; @@ -1209,7 +1224,7 @@ int unit_load(Unit *u) { goto fail; if (u->on_failure_job_mode == JOB_ISOLATE && set_size(u->dependencies[UNIT_ON_FAILURE]) > 1) { - log_error_unit(u->id, "More than one OnFailure= dependencies specified for %s but OnFailureJobMode=isolate set. Refusing.", u->id); + log_unit_error(u->id, "More than one OnFailure= dependencies specified for %s but OnFailureJobMode=isolate set. Refusing.", u->id); r = -EINVAL; goto fail; } @@ -1230,21 +1245,77 @@ fail: unit_add_to_dbus_queue(u); unit_add_to_gc_queue(u); - log_debug_unit(u->id, "Failed to load configuration for %s: %s", + log_unit_debug(u->id, "Failed to load configuration for %s: %s", u->id, strerror(-r)); return r; } +static bool unit_condition_test_list(Unit *u, Condition *first, const char *(*to_string)(ConditionType t)) { + Condition *c; + int triggered = -1; + + assert(u); + assert(to_string); + + /* If the condition list is empty, then it is true */ + if (!first) + return true; + + /* Otherwise, if all of the non-trigger conditions apply and + * if any of the trigger conditions apply (unless there are + * none) we return true */ + LIST_FOREACH(conditions, c, first) { + int r; + + r = condition_test(c); + if (r < 0) + log_unit_warning(u->id, + "Couldn't determine result for %s=%s%s%s for %s, assuming failed: %s", + to_string(c->type), + c->trigger ? "|" : "", + c->negate ? "!" : "", + c->parameter, + u->id, + strerror(-r)); + else + log_unit_debug(u->id, + "%s=%s%s%s %s for %s.", + to_string(c->type), + c->trigger ? "|" : "", + c->negate ? "!" : "", + c->parameter, + condition_result_to_string(c->result), + u->id); + + if (!c->trigger && r <= 0) + return false; + + if (c->trigger && triggered <= 0) + triggered = r > 0; + } + + return triggered != 0; +} + static bool unit_condition_test(Unit *u) { assert(u); dual_timestamp_get(&u->condition_timestamp); - u->condition_result = condition_test_list(u->id, u->conditions); + u->condition_result = unit_condition_test_list(u, u->conditions, condition_type_to_string); return u->condition_result; } +static bool unit_assert_test(Unit *u) { + assert(u); + + dual_timestamp_get(&u->assert_timestamp); + u->assert_result = unit_condition_test_list(u, u->asserts, assert_type_to_string); + + return u->assert_result; +} + _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) { const UnitStatusMessageFormats *format_table; @@ -1322,17 +1393,16 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { 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 : SD_MESSAGE_UNIT_RELOADING; - log_struct_unit(LOG_INFO, - u->id, - MESSAGE_ID(mid), - "MESSAGE=%s", buf, + log_unit_struct(u->id, + LOG_INFO, + LOG_MESSAGE_ID(mid), + LOG_MESSAGE("%s", buf), NULL); } @@ -1341,10 +1411,12 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { * -EALREADY: Unit is already started. * -EAGAIN: An operation is already in progress. Retry later. * -ECANCELED: Too many requests for now. + * -EPROTO: Assert failed */ int unit_start(Unit *u) { UnitActiveState state; Unit *following; + int r; assert(u); @@ -1365,20 +1437,26 @@ int unit_start(Unit *u) { * but we don't want to recheck the condition in that case. */ if (state != UNIT_ACTIVATING && !unit_condition_test(u)) { - log_debug_unit(u->id, "Starting of %s requested but condition failed. Ignoring.", u->id); + log_unit_debug(u->id, "Starting of %s requested but condition failed. Not starting unit.", u->id); return -EALREADY; } + /* If the asserts failed, fail the entire job */ + if (state != UNIT_ACTIVATING && + !unit_assert_test(u)) { + log_unit_debug(u->id, "Starting of %s requested but asserts failed.", u->id); + return -EPROTO; + } + /* Forward to the main object, if we aren't it. */ following = unit_following(u); if (following) { - log_debug_unit(u->id, "Redirecting start request from %s to %s.", - u->id, following->id); + log_unit_debug(u->id, "Redirecting start request from %s to %s.", u->id, following->id); return unit_start(following); } - unit_status_log_starting_stopping_reloading(u, JOB_START); - unit_status_print_starting_stopping(u, JOB_START); + if (UNIT_VTABLE(u)->supported && !UNIT_VTABLE(u)->supported(u->manager)) + return -ENOTSUP; /* If it is stopped, but we cannot start it, then fail */ if (!UNIT_VTABLE(u)->start) @@ -1392,7 +1470,14 @@ int unit_start(Unit *u) { unit_add_to_dbus_queue(u); - return UNIT_VTABLE(u)->start(u); + r = UNIT_VTABLE(u)->start(u); + if (r <= 0) + return r; + + /* Log if the start function actually did something */ + unit_status_log_starting_stopping_reloading(u, JOB_START); + unit_status_print_starting_stopping(u, JOB_START); + return r; } bool unit_can_start(Unit *u) { @@ -1416,6 +1501,7 @@ bool unit_can_isolate(Unit *u) { int unit_stop(Unit *u) { UnitActiveState state; Unit *following; + int r; assert(u); @@ -1423,21 +1509,24 @@ int unit_stop(Unit *u) { if (UNIT_IS_INACTIVE_OR_FAILED(state)) return -EALREADY; - if ((following = unit_following(u))) { - log_debug_unit(u->id, "Redirecting stop request from %s to %s.", - u->id, following->id); + following = unit_following(u); + if (following) { + log_unit_debug(u->id, "Redirecting stop request from %s to %s.", u->id, following->id); return unit_stop(following); } - unit_status_log_starting_stopping_reloading(u, JOB_STOP); - unit_status_print_starting_stopping(u, JOB_STOP); - if (!UNIT_VTABLE(u)->stop) return -EBADR; unit_add_to_dbus_queue(u); - return UNIT_VTABLE(u)->stop(u); + r = UNIT_VTABLE(u)->stop(u); + if (r <= 0) + return r; + + unit_status_log_starting_stopping_reloading(u, JOB_STOP); + unit_status_print_starting_stopping(u, JOB_STOP); + return r; } /* Errors: @@ -1448,6 +1537,7 @@ int unit_stop(Unit *u) { int unit_reload(Unit *u) { UnitActiveState state; Unit *following; + int r; assert(u); @@ -1462,22 +1552,24 @@ int unit_reload(Unit *u) { return -EALREADY; if (state != UNIT_ACTIVE) { - log_warning_unit(u->id, "Unit %s cannot be reloaded because it is inactive.", - u->id); + log_unit_warning(u->id, "Unit %s cannot be reloaded because it is inactive.", u->id); return -ENOEXEC; } following = unit_following(u); if (following) { - log_debug_unit(u->id, "Redirecting reload request from %s to %s.", - u->id, following->id); + log_unit_debug(u->id, "Redirecting reload request from %s to %s.", u->id, following->id); return unit_reload(following); } - unit_status_log_starting_stopping_reloading(u, JOB_RELOAD); - unit_add_to_dbus_queue(u); - return UNIT_VTABLE(u)->reload(u); + + r = UNIT_VTABLE(u)->reload(u); + if (r <= 0) + return r; + + unit_status_log_starting_stopping_reloading(u, JOB_RELOAD); + return r; } bool unit_can_reload(Unit *u) { @@ -1523,7 +1615,7 @@ static void unit_check_unneeded(Unit *u) { if (unit_active_or_pending(other)) return; - log_info_unit(u->id, "Unit %s is not needed anymore. Stopping.", u->id); + log_unit_info(u->id, "Unit %s is not needed anymore. Stopping.", u->id); /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */ manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); @@ -1555,7 +1647,7 @@ static void unit_check_binds_to(Unit *u) { if (!stop) return; - log_info_unit(u->id, "Unit %s is bound to inactive service. Stopping, too.", u->id); + log_unit_info(u->id, "Unit %s is bound to inactive unit. Stopping, too.", u->id); /* A unit we need to run is gone. Sniff. Let's stop this. */ manager_add_job(u->manager, JOB_STOP, u, JOB_FAIL, true, NULL, NULL); @@ -1647,14 +1739,14 @@ void unit_start_on_failure(Unit *u) { if (set_size(u->dependencies[UNIT_ON_FAILURE]) <= 0) return; - log_info_unit(u->id, "Triggering OnFailure= dependencies of %s.", u->id); + log_unit_info(u->id, "Triggering OnFailure= dependencies of %s.", u->id); SET_FOREACH(other, u->dependencies[UNIT_ON_FAILURE], i) { int r; r = manager_add_job(u->manager, JOB_START, other, u->on_failure_job_mode, true, NULL, NULL); if (r < 0) - log_error_unit(u->id, "Failed to enqueue OnFailure= job: %s", strerror(-r)); + log_unit_error_errno(u->id, r, "Failed to enqueue OnFailure= job: %m"); } } @@ -1710,7 +1802,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su /* Make sure the cgroup is always removed when we become inactive */ if (UNIT_IS_INACTIVE_OR_FAILED(ns)) - unit_destroy_cgroup(u); + unit_destroy_cgroup_if_empty(u); /* Note that this doesn't apply to RemainAfterExit services exiting * successfully, since there's no change of state in that case. Which is @@ -1818,7 +1910,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su check_unneeded_dependencies(u); if (ns != os && ns == UNIT_FAILED) { - log_notice_unit(u->id, "Unit %s entered failed state.", u->id); + log_unit_notice(u->id, "Unit %s entered failed state.", u->id); unit_start_on_failure(u); } } @@ -2080,10 +2172,10 @@ static int maybe_warn_about_dependency(const char *id, const char *other, UnitDe case UNIT_TRIGGERS: case UNIT_TRIGGERED_BY: if (streq_ptr(id, other)) - log_warning_unit(id, "Dependency %s=%s dropped from unit %s", + log_unit_warning(id, "Dependency %s=%s dropped from unit %s", unit_dependency_to_string(dependency), id, other); else - log_warning_unit(id, "Dependency %s=%s dropped from unit %s merged into %s", + log_unit_warning(id, "Dependency %s=%s dropped from unit %s merged into %s", unit_dependency_to_string(dependency), id, strna(other), id); return -EINVAL; @@ -2502,10 +2594,14 @@ int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { dual_timestamp_serialize(f, "active-exit-timestamp", &u->active_exit_timestamp); dual_timestamp_serialize(f, "inactive-enter-timestamp", &u->inactive_enter_timestamp); dual_timestamp_serialize(f, "condition-timestamp", &u->condition_timestamp); + dual_timestamp_serialize(f, "assert-timestamp", &u->assert_timestamp); if (dual_timestamp_is_set(&u->condition_timestamp)) unit_serialize_item(u, f, "condition-result", yes_no(u->condition_result)); + if (dual_timestamp_is_set(&u->assert_timestamp)) + unit_serialize_item(u, f, "assert-result", yes_no(u->assert_result)); + unit_serialize_item(u, f, "transient", yes_no(u->transient)); if (u->cgroup_path) @@ -2596,7 +2692,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (streq(l, "job")) { if (v[0] == '\0') { /* new-style serialized job */ - Job *j = job_new_raw(u); + Job *j; + + j = job_new_raw(u); if (!j) return -ENOMEM; @@ -2618,12 +2716,11 @@ 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); + JobType type; + + type = job_type_from_string(v); if (type < 0) log_debug("Failed to parse job type value %s", v); else @@ -2645,6 +2742,9 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { } else if (streq(l, "condition-timestamp")) { dual_timestamp_deserialize(v, &u->condition_timestamp); continue; + } else if (streq(l, "assert-timestamp")) { + dual_timestamp_deserialize(v, &u->assert_timestamp); + continue; } else if (streq(l, "condition-result")) { int b; @@ -2656,6 +2756,17 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { continue; + } else if (streq(l, "assert-result")) { + int b; + + b = parse_boolean(v); + if (b < 0) + log_debug("Failed to parse assert result value %s", v); + else + u->assert_result = b; + + continue; + } else if (streq(l, "transient")) { int b; @@ -2728,7 +2839,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants) { if (r < 0) return r; - r = unit_add_two_dependencies(u, UNIT_AFTER, UNIT_BINDS_TO, device, true); + r = unit_add_two_dependencies(u, UNIT_AFTER, u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_BINDS_TO : UNIT_WANTS, device, true); if (r < 0) return r; @@ -2802,7 +2913,7 @@ bool unit_need_daemon_reload(Unit *u) { return true; } - t = unit_find_dropin_paths(u); + (void) unit_find_dropin_paths(u, &t); loaded_cnt = strv_length(t); current_cnt = strv_length(u->dropin_paths); @@ -2939,18 +3050,16 @@ int unit_kill_common( if (who == KILL_MAIN && main_pid <= 0) { if (main_pid < 0) - sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type)); + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no main processes", unit_type_to_string(u->type)); else - sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill"); - return -ESRCH; + return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No main process to kill"); } if (who == KILL_CONTROL && control_pid <= 0) { if (control_pid < 0) - sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type)); + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_PROCESS, "%s units have no control processes", unit_type_to_string(u->type)); else - sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill"); - return -ESRCH; + return sd_bus_error_set_const(error, BUS_ERROR_NO_SUCH_PROCESS, "No control process to kill"); } if (who == KILL_CONTROL || who == KILL_ALL) @@ -3002,6 +3111,17 @@ UnitFileState unit_get_unit_file_state(Unit *u) { return u->unit_file_state; } +int unit_get_unit_file_preset(Unit *u) { + assert(u); + + if (u->unit_file_preset < 0 && u->fragment_path) + u->unit_file_preset = unit_file_query_preset( + u->manager->running_as == SYSTEMD_SYSTEM ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, + NULL, basename(u->fragment_path)); + + return u->unit_file_preset; +} + Unit* unit_ref_set(UnitRef *ref, Unit *u) { assert(ref); assert(u); @@ -3052,6 +3172,10 @@ int unit_patch_contexts(Unit *u) { r = get_home_dir(&ec->working_directory); if (r < 0) return r; + + /* Allow user services to run, even if the + * home directory is missing */ + ec->working_directory_missing_ok = true; } if (u->manager->running_as == SYSTEMD_USER && @@ -3172,7 +3296,7 @@ static int unit_drop_in_file(Unit *u, int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *data) { - _cleanup_free_ char *dir = NULL; + _cleanup_free_ char *dir = NULL, *p = NULL, *q = NULL; int r; assert(u); @@ -3184,7 +3308,24 @@ int unit_write_drop_in(Unit *u, UnitSetPropertiesMode mode, const char *name, co if (r < 0) return r; - return write_drop_in(dir, u->id, 50, name, data); + r = write_drop_in(dir, u->id, 50, name, data); + if (r < 0) + return r; + + r = drop_in_file(dir, u->id, 50, name, &p, &q); + if (r < 0) + return r; + + r = strv_extend(&u->dropin_paths, q); + if (r < 0) + return r; + + strv_sort(u->dropin_paths); + strv_uniq(u->dropin_paths); + + u->dropin_mtime = now(CLOCK_REALTIME); + + return 0; } int unit_write_drop_in_format(Unit *u, UnitSetPropertiesMode mode, const char *name, const char *format, ...) { @@ -3313,7 +3454,7 @@ int unit_make_transient(Unit *u) { int unit_kill_context( Unit *u, KillContext *c, - bool sigkill, + KillOperation k, pid_t main_pid, pid_t control_pid, bool main_pid_alien) { @@ -3326,7 +3467,19 @@ int unit_kill_context( if (c->kill_mode == KILL_NONE) return 0; - sig = sigkill ? SIGKILL : c->kill_signal; + switch (k) { + case KILL_KILL: + sig = SIGKILL; + break; + case KILL_ABORT: + sig = SIGABRT; + break; + case KILL_TERMINATE: + sig = c->kill_signal; + break; + default: + assert_not_reached("KillOperation unknown"); + } if (main_pid > 0) { r = kill_and_sigcont(main_pid, sig); @@ -3335,12 +3488,12 @@ int unit_kill_context( _cleanup_free_ char *comm = NULL; get_process_comm(main_pid, &comm); - log_warning_unit(u->id, "Failed to kill main process " PID_FMT " (%s): %s", main_pid, strna(comm), strerror(-r)); + log_unit_warning_errno(u->id, r, "Failed to kill main process " PID_FMT " (%s): %m", main_pid, strna(comm)); } else { if (!main_pid_alien) wait_for_exit = true; - if (c->send_sighup && !sigkill) + if (c->send_sighup && k != KILL_KILL) kill(main_pid, SIGHUP); } } @@ -3352,16 +3505,16 @@ int unit_kill_context( _cleanup_free_ char *comm = NULL; get_process_comm(control_pid, &comm); - log_warning_unit(u->id, "Failed to kill control process " PID_FMT " (%s): %s", control_pid, strna(comm), strerror(-r)); + log_unit_warning_errno(u->id, r, "Failed to kill control process " PID_FMT " (%s): %m", control_pid, strna(comm)); } else { wait_for_exit = true; - if (c->send_sighup && !sigkill) + if (c->send_sighup && k != KILL_KILL) kill(control_pid, SIGHUP); } } - if ((c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && sigkill)) && u->cgroup_path) { + if ((c->kill_mode == KILL_CONTROL_GROUP || (c->kill_mode == KILL_MIXED && k == KILL_KILL)) && u->cgroup_path) { _cleanup_set_free_ Set *pid_set = NULL; /* Exclude the main/control pids from being killed via the cgroup */ @@ -3372,7 +3525,7 @@ int unit_kill_context( r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, sig, true, true, false, pid_set); if (r < 0) { if (r != -EAGAIN && r != -ESRCH && r != -ENOENT) - log_warning_unit(u->id, "Failed to kill control group: %s", strerror(-r)); + log_unit_warning_errno(u->id, r, "Failed to kill control group: %m"); } else if (r > 0) { /* FIXME: For now, we will not wait for the @@ -3385,7 +3538,7 @@ int unit_kill_context( /* wait_for_exit = true; */ - if (c->send_sighup && !sigkill) { + if (c->send_sighup && k != KILL_KILL) { set_free(pid_set); pid_set = unit_pid_set(main_pid, control_pid);