+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
assert(s);
watchdog_usec = service_get_watchdog_usec(s);
- if (watchdog_usec == 0 || watchdog_usec == USEC_INFINITY)
+ if (IN_SET(watchdog_usec, 0, USEC_INFINITY))
return;
if (s->watchdog_event_source) {
static void service_release_fd_store(Service *s) {
assert(s);
+ if (s->n_keep_fd_store > 0)
+ return;
+
log_unit_debug(UNIT(s), "Releasing all stored fds");
while (s->fd_store)
service_fd_store_unlink(s->fd_store);
assert(s->n_fd_store == 0);
}
-static void service_release_resources(Unit *u, bool inactive) {
+static void service_release_resources(Unit *u) {
Service *s = SERVICE(u);
assert(s);
s->stdout_fd = safe_close(s->stdout_fd);
s->stderr_fd = safe_close(s->stderr_fd);
- if (inactive)
- service_release_fd_store(s);
+ service_release_fd_store(s);
}
static void service_done(Unit *u) {
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
- service_release_resources(u, true);
+ service_release_resources(u);
}
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) {
if (s->bus_name && s->type != SERVICE_DBUS)
log_unit_warning(UNIT(s), "Service has a D-Bus service name specified, but is not of type dbus. Ignoring.");
- if (s->exec_context.pam_name && !(s->kill_context.kill_mode == KILL_CONTROL_GROUP || s->kill_context.kill_mode == KILL_MIXED)) {
+ if (s->exec_context.pam_name && !IN_SET(s->kill_context.kill_mode, KILL_CONTROL_GROUP, KILL_MIXED)) {
log_unit_error(UNIT(s), "Service has PAM enabled. Kill mode must be set to 'control-group' or 'mixed'. Refusing.");
return -EINVAL;
}
* require it, so that we fail if we can't acquire
* it. */
- r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
+ r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
} else {
/* In the --user instance there's no sysinit.target,
* in that case require basic.target instead. */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_BASIC_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
}
/* Second, if the rest of the base system is in the same
* transaction, order us after it, but do not pull it in or
* even require it. */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, NULL, true);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_BASIC_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
if (r < 0)
return r;
/* Third, add us in for normal shutdown. */
- return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
+ return unit_add_two_dependencies_by_name(UNIT(s), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
}
static void service_fix_output(Service *s) {
if (!s->bus_name)
return 0;
- r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_REQUIRES, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
/* We always want to be ordered against dbus.socket if both are in the transaction. */
- r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true);
+ r = unit_add_dependency_by_name(UNIT(s), UNIT_AFTER, SPECIAL_DBUS_SOCKET, NULL, true, UNIT_DEPENDENCY_FILE);
if (r < 0)
return log_unit_error_errno(UNIT(s), r, "Failed to add dependency on " SPECIAL_DBUS_SOCKET ": %m");
"%sFile Descriptor Store Current: %u\n",
prefix, s->n_fd_store_max,
prefix, s->n_fd_store);
+
+ cgroup_context_dump(&s->cgroup_context, f, prefix);
}
static int service_load_pid_file(Service *s, bool may_warn) {
rn_socket_fds = 1;
} else {
Iterator i;
+ void *v;
Unit *u;
/* Pass all our configured sockets for singleton services */
- SET_FOREACH(u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) {
+ HASHMAP_FOREACH_KEY(v, u, UNIT(s)->dependencies[UNIT_TRIGGERED_BY], i) {
_cleanup_free_ int *cfds = NULL;
Socket *sock;
int cn_fds;
_cleanup_strv_free_ char **final_env = NULL, **our_env = NULL, **fd_names = NULL;
_cleanup_free_ int *fds = NULL;
unsigned n_storage_fds = 0, n_socket_fds = 0, n_env = 0;
- const char *path;
pid_t pid;
ExecParameters exec_params = {
if (flags & EXEC_IS_CONTROL) {
/* If this is a control process, mask the permissions/chroot application if this is requested. */
if (s->permissions_start_only)
- exec_params.flags &= ~EXEC_APPLY_PERMISSIONS;
+ exec_params.flags &= ~EXEC_APPLY_SANDBOXING;
if (s->root_directory_start_only)
exec_params.flags &= ~EXEC_APPLY_CHROOT;
}
(void) unit_realize_cgroup(UNIT(s));
- if (s->reset_cpu_usage) {
- (void) unit_reset_cpu_usage(UNIT(s));
- s->reset_cpu_usage = false;
+ if (s->reset_accounting) {
+ (void) unit_reset_cpu_accounting(UNIT(s));
+ (void) unit_reset_ip_accounting(UNIT(s));
+ s->reset_accounting = false;
}
+ unit_export_state_files(UNIT(s));
+
r = unit_setup_exec_runtime(UNIT(s));
if (r < 0)
return r;
union sockaddr_union sa;
socklen_t salen = sizeof(sa);
- r = getpeername(s->socket_fd, &sa.sa, &salen);
- if (r < 0) {
- r = -errno;
+ /* If this is a per-connection service instance, let's set $REMOTE_ADDR and $REMOTE_PORT to something
+ * useful. Note that we do this only when we are still connected at this point in time, which we might
+ * very well not be. Hence we ignore all errors when retrieving peer information (as that might result
+ * in ENOTCONN), and just use whate we can use. */
- /* ENOTCONN is legitimate if the endpoint disappeared on shutdown.
- * This connection is over, but the socket unit lives on. */
- if (r != -ENOTCONN || !IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST))
- return r;
- }
+ if (getpeername(s->socket_fd, &sa.sa, &salen) >= 0 &&
+ IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
- if (r == 0 && IN_SET(sa.sa.sa_family, AF_INET, AF_INET6, AF_VSOCK)) {
_cleanup_free_ char *addr = NULL;
char *t;
unsigned port;
}
}
- r = manager_set_exec_params(UNIT(s)->manager, &exec_params);
- if (r < 0)
- return r;
+ manager_set_exec_params(UNIT(s)->manager, &exec_params);
+ unit_set_exec_params(UNIT(s), &exec_params);
final_env = strv_env_merge(2, exec_params.environment, our_env, NULL);
if (!final_env)
return -ENOMEM;
if ((flags & EXEC_IS_CONTROL) && UNIT(s)->cgroup_path) {
- path = strjoina(UNIT(s)->cgroup_path, "/control");
- (void) cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
- } else
- path = UNIT(s)->cgroup_path;
+ exec_params.cgroup_path = strjoina(UNIT(s)->cgroup_path, "/control");
+ (void) cg_create(SYSTEMD_CGROUP_CONTROLLER, exec_params.cgroup_path);
+ }
+
+ /* System services should get a new keyring by default. */
+ SET_FLAG(exec_params.flags, EXEC_NEW_KEYRING, MANAGER_IS_SYSTEM(UNIT(s)->manager));
+
+ /* System D-Bus needs nss-systemd disabled, so that we don't deadlock */
+ SET_FLAG(exec_params.flags, EXEC_NSS_BYPASS_BUS,
+ MANAGER_IS_SYSTEM(UNIT(s)->manager) && unit_has_name(UNIT(s), SPECIAL_DBUS_SERVICE));
- exec_params.flags |= MANAGER_IS_SYSTEM(UNIT(s)->manager) ? EXEC_NEW_KEYRING : 0;
exec_params.argv = c->argv;
exec_params.environment = final_env;
exec_params.fds = fds;
exec_params.fd_names = fd_names;
exec_params.n_storage_fds = n_storage_fds;
exec_params.n_socket_fds = n_socket_fds;
- exec_params.cgroup_path = path;
- exec_params.cgroup_delegate = s->cgroup_context.delegate;
exec_params.watchdog_usec = s->watchdog_usec;
exec_params.selinux_context_net = s->socket_fd_selinux_context_net;
if (s->type == SERVICE_IDLE)
static int main_pid_good(Service *s) {
assert(s);
- /* Returns 0 if the pid is dead, 1 if it is good, -1 if we
- * don't know */
+ /* Returns 0 if the pid is dead, > 0 if it is good, < 0 if we don't know */
/* If we know the pid file, then let's just check if it is
* still valid */
return -EAGAIN;
}
-_pure_ static int control_pid_good(Service *s) {
+static int control_pid_good(Service *s) {
assert(s);
+ /* Returns 0 if the control PID is dead, > 0 if it is good. We never actually return < 0 here, but in order to
+ * make this function as similar as possible to main_pid_good() and cgroup_good(), we pretend that < 0 also
+ * means: we can't figure it out. */
+
return s->control_pid > 0;
}
assert(s);
+ /* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't
+ * figure it out */
+
if (!UNIT(s)->cgroup_path)
return 0;
if (r < 0)
return r;
- return !r;
+ return r == 0;
}
static bool service_shall_restart(Service *s) {
static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
int r;
+
assert(s);
+ /* If there's a stop job queued before we enter the DEAD state, we shouldn't act on Restart=, in order to not
+ * undo what has already been enqueued. */
+ if (unit_stop_pending(UNIT(s)))
+ allow_restart = false;
+
if (s->result == SERVICE_SUCCESS)
s->result = f;
+ if (s->result != SERVICE_SUCCESS)
+ log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result));
+
+ /* Make sure service_release_resources() doesn't destroy our FD store, while we are changing through
+ * SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */
+ s->n_keep_fd_store ++;
+
service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
- if (s->result != SERVICE_SUCCESS) {
- log_unit_warning(UNIT(s), "Failed with result '%s'.", service_result_to_string(s->result));
+ if (s->result != SERVICE_SUCCESS)
emergency_action(UNIT(s)->manager, s->emergency_action, UNIT(s)->reboot_arg, "service failed");
- }
if (allow_restart && service_shall_restart(s)) {
r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec));
- if (r < 0)
+ if (r < 0) {
+ s->n_keep_fd_store--;
goto fail;
+ }
service_set_state(s, SERVICE_AUTO_RESTART);
} else
* user can still introspect the counter. Do so on the next start. */
s->flush_n_restarts = true;
+ /* The new state is in effect, let's decrease the fd store ref counter again. Let's also readd us to the GC
+ * queue, so that the fd store is possibly gc'ed again */
+ s->n_keep_fd_store--;
+ unit_add_to_gc_queue(UNIT(s));
+
/* The next restart might not be a manual stop, hence reset the flag indicating manual stops */
s->forbid_restart = false;
r = service_spawn(s,
s->control_command,
s->timeout_stop_usec,
- EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT,
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_IS_CONTROL|EXEC_SETENV_RESULT,
&s->control_pid);
if (r < 0)
goto fail;
s->main_pid,
s->control_pid,
s->main_pid_alien);
-
if (r < 0)
goto fail;
r = service_spawn(s,
s->control_command,
s->timeout_stop_usec,
- EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT,
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_SETENV_RESULT,
&s->control_pid);
if (r < 0)
goto fail;
r = service_spawn(s,
s->control_command,
s->timeout_start_usec,
- EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL,
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL,
&s->control_pid);
if (r < 0)
goto fail;
}
static void service_kill_control_processes(Service *s) {
- char *p;
+ int r;
- if (!UNIT(s)->cgroup_path)
- return;
+ assert(s);
+
+ if (s->control_pid > 0) {
+ r = kill_and_sigcont(s->control_pid, SIGKILL);
+ if (r < 0) {
+ _cleanup_free_ char *comm = NULL;
+
+ (void) get_process_comm(s->control_pid, &comm);
+
+ log_unit_debug_errno(UNIT(s), r, "Failed to kill control process " PID_FMT " (%s), ignoring: %m",
+ s->control_pid, strna(comm));
+ }
+ }
- p = strjoina(UNIT(s)->cgroup_path, "/control");
- cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, CGROUP_SIGCONT|CGROUP_IGNORE_SELF|CGROUP_REMOVE, NULL, NULL, NULL);
+ if (UNIT(s)->cgroup_path) {
+ _cleanup_set_free_ Set *pid_set = NULL;
+ char *p;
+
+ if (s->control_pid > 0) {
+ r = set_make(&pid_set, PID_TO_PTR(s->control_pid), NULL);
+ if (r < 0) {
+ log_oom();
+ return;
+ }
+ }
+
+ p = strjoina(UNIT(s)->cgroup_path, "/control");
+ r = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, p, SIGKILL, CGROUP_SIGCONT|CGROUP_IGNORE_SELF|CGROUP_REMOVE, pid_set, NULL, NULL);
+ if (r < 0)
+ log_unit_debug_errno(UNIT(s), r, "Failed to send SIGKILL to processes of control group %s: %m", p);
+ }
}
static void service_enter_start(Service *s) {
r = service_spawn(s,
c,
timeout,
- EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG,
+ EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG,
&pid);
if (r < 0)
goto fail;
r = service_spawn(s,
s->control_command,
s->timeout_start_usec,
- EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN,
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_APPLY_TTY_STDIN,
&s->control_pid);
if (r < 0)
goto fail;
log_struct(LOG_INFO,
"MESSAGE_ID=" SD_MESSAGE_UNIT_RESTART_SCHEDULED_STR,
LOG_UNIT_ID(UNIT(s)),
+ LOG_UNIT_INVOCATION_ID(UNIT(s)),
LOG_UNIT_MESSAGE(UNIT(s), "Scheduled restart job, restart counter is at %u.", s->n_restarts),
"N_RESTARTS=%u", s->n_restarts,
NULL);
r = service_spawn(s,
s->control_command,
s->timeout_start_usec,
- EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL,
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL,
&s->control_pid);
if (r < 0)
goto fail;
r = service_spawn(s,
s->control_command,
timeout,
- EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|
+ EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|
(IN_SET(s->control_command_id, SERVICE_EXEC_START_PRE, SERVICE_EXEC_STOP_POST) ? EXEC_APPLY_TTY_STDIN : 0)|
(IN_SET(s->control_command_id, SERVICE_EXEC_STOP, SERVICE_EXEC_STOP_POST) ? EXEC_SETENV_RESULT : 0),
&s->control_pid);
fail:
log_unit_warning_errno(UNIT(s), r, "Failed to run next control task: %m");
- if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_STOP))
+ if (IN_SET(s->state, SERVICE_START_PRE, SERVICE_START_POST, SERVICE_STOP))
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_RESOURCES);
else if (s->state == SERVICE_STOP_POST)
service_enter_dead(s, SERVICE_FAILURE_RESOURCES, true);
r = service_spawn(s,
s->main_command,
s->timeout_start_usec,
- EXEC_PASS_FDS|EXEC_APPLY_PERMISSIONS|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG,
+ EXEC_PASS_FDS|EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_APPLY_TTY_STDIN|EXEC_SET_WATCHDOG,
&pid);
if (r < 0)
goto fail;
s->main_pid_known = false;
s->main_pid_alien = false;
s->forbid_restart = false;
- s->reset_cpu_usage = true;
+ s->reset_accounting = true;
s->status_text = mfree(s->status_text);
s->status_errno = 0;
assert(s);
- assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED);
+ assert(IN_SET(s->state, SERVICE_RUNNING, SERVICE_EXITED));
service_enter_reload(s);
return 1;
unit_serialize_item(u, f, "bus-name-owner", s->bus_name_owner);
unit_serialize_item_format(u, f, "n-restarts", "%u", s->n_restarts);
- unit_serialize_item(u, f, "n-restarts", yes_no(s->flush_n_restarts));
+ unit_serialize_item(u, f, "flush-n-restarts", yes_no(s->flush_n_restarts));
r = unit_serialize_item_escaped(u, f, "status-text", s->status_text);
if (r < 0)
int r;
assert(s->pid_file);
- assert(s->state == SERVICE_START || s->state == SERVICE_START_POST);
+ assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST));
r = service_load_pid_file(s, false);
if (r < 0)
assert(s);
assert(fd >= 0);
- assert(s->state == SERVICE_START || s->state == SERVICE_START_POST);
+ assert(IN_SET(s->state, SERVICE_START, SERVICE_START_POST));
assert(s->pid_file_pathspec);
assert(path_spec_owns_inotify_fd(s->pid_file_pathspec, fd));
* SIGCHLD for. */
case SERVICE_START:
- if (s->type == SERVICE_NOTIFY) {
+ if (s->type == SERVICE_NOTIFY &&
+ main_pid_good(s) == 0 &&
+ control_pid_good(s) == 0) {
/* No chance of getting a ready notification anymore */
service_enter_stop_post(s, SERVICE_FAILURE_PROTOCOL);
break;
/* Fall through */
case SERVICE_START_POST:
- if (s->pid_file_pathspec) {
+ if (s->pid_file_pathspec &&
+ main_pid_good(s) == 0 &&
+ control_pid_good(s) == 0) {
+
/* Give up hoping for the daemon to write its PID file */
log_unit_warning(u, "Daemon never wrote its PID file. Failing.");
case SERVICE_STOP_SIGTERM:
case SERVICE_STOP_SIGKILL:
- if (main_pid_good(s) <= 0 && !control_pid_good(s))
+ if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0)
service_enter_stop_post(s, SERVICE_SUCCESS);
break;
case SERVICE_STOP_POST:
case SERVICE_FINAL_SIGTERM:
case SERVICE_FINAL_SIGKILL:
- if (main_pid_good(s) <= 0 && !control_pid_good(s))
+ if (main_pid_good(s) <= 0 && control_pid_good(s) <= 0)
service_enter_dead(s, SERVICE_SUCCESS, true);
break;
s->main_command->exec_status = s->main_exec_status;
- if (s->main_command->ignore)
+ if (s->main_command->flags & EXEC_COMMAND_IGNORE_FAILURE)
f = SERVICE_SUCCESS;
} else if (s->exec_command[SERVICE_EXEC_START]) {
* ignore the return value if this was
* configured for the starter process */
- if (s->exec_command[SERVICE_EXEC_START]->ignore)
+ if (s->exec_command[SERVICE_EXEC_START]->flags & EXEC_COMMAND_IGNORE_FAILURE)
f = SERVICE_SUCCESS;
}
"EXIT_CODE=%s", sigchld_code_to_string(code),
"EXIT_STATUS=%i", status,
LOG_UNIT_ID(u),
+ LOG_UNIT_INVOCATION_ID(u),
NULL);
if (s->result == SERVICE_SUCCESS)
if (s->main_command &&
s->main_command->command_next &&
+ s->type == SERVICE_ONESHOT &&
f == SERVICE_SUCCESS) {
/* There is another command to *
* has been received */
if (f != SERVICE_SUCCESS)
service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
- else if (!s->remain_after_exit)
- /* The service has never been active */
+ else if (!s->remain_after_exit || s->notify_access == NOTIFY_MAIN)
+ /* The service has never been and will never be active */
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
case SERVICE_STOP_SIGTERM:
case SERVICE_STOP_SIGKILL:
- if (!control_pid_good(s))
+ if (control_pid_good(s) <= 0)
service_enter_stop_post(s, f);
/* If there is still a control process, wait for that first */
case SERVICE_FINAL_SIGTERM:
case SERVICE_FINAL_SIGKILL:
- if (!control_pid_good(s))
+ if (control_pid_good(s) <= 0)
service_enter_dead(s, f, true);
break;
if (s->control_command) {
exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status);
- if (s->control_command->ignore)
+ if (s->control_command->flags & EXEC_COMMAND_IGNORE_FAILURE)
f = SERVICE_SUCCESS;
}
r = service_load_pid_file(s, !has_start_post);
if (!has_start_post && r < 0) {
r = service_demand_pid_file(s);
- if (r < 0 || !cgroup_good(s))
+ if (r < 0 || cgroup_good(s) == 0)
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_FAILURE_PROTOCOL);
break;
}
r = service_load_pid_file(s, true);
if (r < 0) {
r = service_demand_pid_file(s);
- if (r < 0 || !cgroup_good(s))
+ if (r < 0 || cgroup_good(s) == 0)
service_enter_stop(s, SERVICE_FAILURE_PROTOCOL);
break;
}
/* If the PID set is empty now, then let's finish this off
(On unified we use proper notifications) */
if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) == 0 && set_isempty(u->pids))
- service_notify_cgroup_empty_event(u);
+ unit_add_to_cgroup_empty_queue(u);
}
static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
}
if (!streq_ptr(s->status_text, t)) {
-
free_and_replace(s->status_text, t);
-
notify_dbus = true;
}
}
} else if (new_owner &&
s->main_pid <= 0 &&
- (s->state == SERVICE_START ||
- s->state == SERVICE_START_POST ||
- s->state == SERVICE_RUNNING ||
- s->state == SERVICE_RELOAD)) {
+ IN_SET(s->state,
+ SERVICE_START,
+ SERVICE_START_POST,
+ SERVICE_RUNNING,
+ SERVICE_RELOAD)) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
pid_t pid;
return r;
}
- r = unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false);
+ r = unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false, UNIT_DEPENDENCY_IMPLICIT);
if (r < 0)
return r;
static int service_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
Service *s = SERVICE(u);
+ assert(s);
+
return unit_kill_common(u, who, signo, s->main_pid, s->control_pid, error);
}