X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Fcore%2Fservice.c;h=a68e5c9f3df75fb498f80dfa04ae0bddede6320b;hb=53e1b683907c2f12330f00feb9630150196f064d;hp=4510ac2423fdf54b60d1576c4c67c46a005a5690;hpb=3ed0cd26ea96e4bcc09846fb76851095c4ec85a8;p=thirdparty%2Fsystemd.git diff --git a/src/core/service.c b/src/core/service.c index 4510ac2423f..a68e5c9f3df 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: LGPL-2.1+ */ /*** This file is part of systemd. @@ -218,7 +219,7 @@ static void service_start_watchdog(Service *s) { 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) { @@ -294,6 +295,9 @@ static void service_fd_store_unlink(ServiceFDStore *fs) { 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); @@ -301,7 +305,7 @@ static void service_release_fd_store(Service *s) { 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); @@ -315,8 +319,7 @@ static void service_release_resources(Unit *u, bool inactive) { 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) { @@ -360,7 +363,7 @@ 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) { @@ -529,7 +532,7 @@ static int service_verify(Service *s) { 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; } @@ -562,7 +565,7 @@ static int service_add_default_dependencies(Service *s) { * 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 { @@ -570,7 +573,7 @@ static int service_add_default_dependencies(Service *s) { /* 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; } @@ -578,12 +581,12 @@ static int service_add_default_dependencies(Service *s) { /* 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) { @@ -612,12 +615,12 @@ static int service_setup_bus_name(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"); @@ -803,6 +806,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { "%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) { @@ -1101,11 +1106,12 @@ static int service_collect_fds(Service *s, 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; @@ -1218,7 +1224,6 @@ static int service_spawn( _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 = { @@ -1237,17 +1242,20 @@ static int service_spawn( 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; @@ -1292,17 +1300,14 @@ static int service_spawn( 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; @@ -1344,29 +1349,31 @@ static int service_spawn( } } - 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) @@ -1397,8 +1404,7 @@ static int service_spawn( 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 */ @@ -1419,9 +1425,13 @@ static int main_pid_good(Service *s) { 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; } @@ -1430,6 +1440,9 @@ static int cgroup_good(Service *s) { 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; @@ -1437,7 +1450,7 @@ static int cgroup_good(Service *s) { if (r < 0) return r; - return !r; + return r == 0; } static bool service_shall_restart(Service *s) { @@ -1497,23 +1510,36 @@ static bool service_will_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 @@ -1521,6 +1547,11 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) * 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; @@ -1569,7 +1600,7 @@ static void service_enter_stop_post(Service *s, ServiceResult f) { 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; @@ -1621,7 +1652,6 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f s->main_pid, s->control_pid, s->main_pid_alien); - if (r < 0) goto fail; @@ -1680,7 +1710,7 @@ static void service_enter_stop(Service *s, ServiceResult f) { 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; @@ -1759,7 +1789,7 @@ static void service_enter_start_post(Service *s) { 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; @@ -1776,13 +1806,39 @@ 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) { @@ -1837,7 +1893,7 @@ 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; @@ -1896,7 +1952,7 @@ static void service_enter_start_pre(Service *s) { 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; @@ -1946,6 +2002,7 @@ static void service_enter_restart(Service *s) { 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); @@ -1994,7 +2051,7 @@ static void service_enter_reload(Service *s) { 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; @@ -2032,7 +2089,7 @@ static void service_run_next_control(Service *s) { 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); @@ -2044,7 +2101,7 @@ static void service_run_next_control(Service *s) { 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); @@ -2070,7 +2127,7 @@ static void service_run_next_main(Service *s) { 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; @@ -2129,7 +2186,7 @@ static int service_start(Unit *u) { 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; @@ -2187,7 +2244,7 @@ static int service_reload(Unit *u) { 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; @@ -2298,7 +2355,7 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { 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) @@ -2718,7 +2775,7 @@ static int service_retry_pid_file(Service *s) { 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) @@ -2789,7 +2846,7 @@ static int service_dispatch_io(sd_event_source *source, int fd, uint32_t events, 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)); @@ -2828,7 +2885,9 @@ static void service_notify_cgroup_empty_event(Unit *u) { * 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; @@ -2837,7 +2896,10 @@ static void service_notify_cgroup_empty_event(Unit *u) { /* 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."); @@ -2858,7 +2920,7 @@ static void service_notify_cgroup_empty_event(Unit *u) { 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; @@ -2866,7 +2928,7 @@ static void service_notify_cgroup_empty_event(Unit *u) { 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; @@ -2941,6 +3003,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { "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) @@ -2948,6 +3011,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { if (s->main_command && s->main_command->command_next && + s->type == SERVICE_ONESHOT && f == SERVICE_SUCCESS) { /* There is another command to * @@ -2985,8 +3049,8 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { * 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; } @@ -3001,7 +3065,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { 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 */ @@ -3011,7 +3075,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { 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; @@ -3092,7 +3156,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { 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; } @@ -3114,7 +3178,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { 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; } @@ -3175,7 +3239,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { /* 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) { @@ -3398,9 +3462,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds) } if (!streq_ptr(s->status_text, t)) { - free_and_replace(s->status_text, t); - notify_dbus = true; } } @@ -3510,10 +3572,11 @@ static void service_bus_name_owner_change( } 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; @@ -3568,7 +3631,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context 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; @@ -3596,6 +3659,8 @@ static void service_reset_failed(Unit *u) { 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); }