along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <assert.h>
#include <errno.h>
#include <string.h>
-#include <sys/epoll.h>
-#include <sys/timerfd.h>
-#include <sys/poll.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#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] = {
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;
}
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)
free(u->cgroup_path);
}
- set_remove(u->manager->failed_units, u);
+ manager_update_failed_units(u->manager, u, false);
set_remove(u->manager->startup_units, u);
free(u->description);
strv_free(u->dropin_paths);
free(u->instance);
+ free(u->job_timeout_reboot_arg);
+
set_free_free(u->names);
unit_unwatch_all_pids(u);
condition_free_list(u->conditions);
+ condition_free_list(u->asserts);
unit_ref_unset(&u->slice);
/*
* 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])
assert(u->type >= 0);
prefix = strempty(prefix);
- prefix2 = strappenda(prefix, "\t");
+ prefix2 = strjoina(prefix, "\t");
fprintf(f,
"%s-> Unit %s:\n"
if (u->job_timeout > 0)
fprintf(f, "%s\tJob Timeout: %s\n", prefix, format_timespan(timespan, sizeof(timespan), u->job_timeout, 0));
- condition_dump_list(u->conditions, f, prefix);
+ if (u->job_timeout_action != FAILURE_ACTION_NONE)
+ fprintf(f, "%s\tJob Timeout Action: %s\n", prefix, failure_action_to_string(u->job_timeout_action));
+
+ 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_type_to_string);
+ condition_dump_list(u->asserts, f, prefix, assert_type_to_string);
if (dual_timestamp_is_set(&u->condition_timestamp))
fprintf(f,
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;
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;
}
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;
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);
}
* -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);
* 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)
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) {
int unit_stop(Unit *u) {
UnitActiveState state;
Unit *following;
+ int r;
assert(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:
int unit_reload(Unit *u) {
UnitActiveState state;
Unit *following;
+ int r;
assert(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) {
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);
continue;
stop = true;
+ break;
}
if (!stop)
return;
- log_info_unit(u->id, "Unit %s is bound to inactive service. Stopping, too.", u->id);
+ assert(other);
+ log_unit_info(u->id, "Unit %s is bound to inactive unit %s. Stopping, too.", u->id, other->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);
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");
}
}
}
/* Keep track of failed units */
- if (ns == UNIT_FAILED)
- set_put(u->manager->failed_units, u);
- else
- set_remove(u->manager->failed_units, u);
+ manager_update_failed_units(u->manager, u, ns == UNIT_FAILED);
/* 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
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);
}
}
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;
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));
+ unit_serialize_item_format(u, f, "cpuacct-usage-base", "%" PRIu64, u->cpuacct_usage_base);
if (u->cgroup_path)
unit_serialize_item(u, f, "cgroup", u->cgroup_path);
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;
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
} 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;
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;
u->transient = b;
continue;
+ } else if (streq(l, "cpuacct-usage-base")) {
+
+ r = safe_atou64(v, &u->cpuacct_usage_base);
+ if (r < 0)
+ log_debug("Failed to parse CPU usage %s", v);
+
} else if (streq(l, "cgroup")) {
char *s;
void *p;
p = hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
- log_info("Removing cgroup_path %s from hashmap (%p)",
- u->cgroup_path, p);
+ log_info("Removing cgroup_path %s from hashmap (%p)", u->cgroup_path, p);
free(u->cgroup_path);
}
return -ENOMEM;
r = manager_load_unit(u->manager, e, NULL, NULL, &device);
-
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;
return 0;
}
-int unit_coldplug(Unit *u) {
+static int unit_add_deserialized_job_coldplug(Unit *u) {
+ int r;
+
+ r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
+ if (r < 0)
+ return r;
+
+ u->deserialized_job = _JOB_TYPE_INVALID;
+
+ return 0;
+}
+
+int unit_coldplug(Unit *u, Hashmap *deferred_work) {
int r;
assert(u);
if (UNIT_VTABLE(u)->coldplug)
- if ((r = UNIT_VTABLE(u)->coldplug(u)) < 0)
+ if ((r = UNIT_VTABLE(u)->coldplug(u, deferred_work)) < 0)
return r;
if (u->job) {
r = job_coldplug(u->job);
if (r < 0)
return r;
- } else if (u->deserialized_job >= 0) {
+ } else if (u->deserialized_job >= 0)
/* legacy */
- r = manager_add_job(u->manager, u->deserialized_job, u, JOB_IGNORE_REQUIREMENTS, false, NULL, NULL);
- if (r < 0)
- return r;
-
- u->deserialized_job = _JOB_TYPE_INVALID;
- }
+ hashmap_put(deferred_work, u, &unit_add_deserialized_job_coldplug);
return 0;
}
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));
+ manager_status_printf(u->manager, STATUS_TYPE_NORMAL,
+ status, unit_status_msg_format, unit_description(u));
REENABLE_WARNING;
}
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);
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)
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);
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 &&
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);
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, ...) {
int unit_kill_context(
Unit *u,
KillContext *c,
- bool sigkill,
+ KillOperation k,
pid_t main_pid,
pid_t control_pid,
bool main_pid_alien) {
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);
_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);
}
}
_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 */
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
/* 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);