summaryrefslogtreecommitdiffstats
path: root/src/core/service.c
diff options
context:
space:
mode:
authorAnita Zhang <the.anitazha@gmail.com>2019-02-21 19:37:40 +0100
committerLennart Poettering <lennart@poettering.net>2019-02-26 10:18:39 +0100
commite51237253ecd343caac88f642049765b33c946ec (patch)
treeb3ef41df8904117ea4092d3fa9e7496422b83b2c /src/core/service.c
parentMerge pull request #11780 from yuwata/fix-4211 (diff)
downloadsystemd-e51237253ecd343caac88f642049765b33c946ec.tar.xz
systemd-e51237253ecd343caac88f642049765b33c946ec.zip
core: consider non-SERVICE_EXEC_START commands for EXIT_CLEAN_COMMAND
When there are multiple ExecStop= statements, the next command would continue to run even after TimeoutStopSec= is up and sends SIGTERM. This is because, unless Type= is oneshot, the exit code/status would evaluate to SERVICE_SUCCESS in service_sigchld_event()'s call to is_clean_exit(). This success indicates following commands would continue running until the end of the list is reached, or another timeout is hit and SIGKILL is sent. Since long running processes should not be invoked in non-SERVICE_EXEC_START commands, consider them for EXIT_CLEAN_COMMAND instead of EXIT_CLEAN_DAEMON. Passing EXIT_CLEAN_COMMAND to is_clean_exit() evaluates the SIGTERM exit code/status to failure and will stop execution after the first timeout is hit. Fixes #11431
Diffstat (limited to 'src/core/service.c')
-rw-r--r--src/core/service.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/src/core/service.c b/src/core/service.c
index 7aa58dd2ca..fc4e92389b 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -3214,11 +3214,19 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
bool notify_dbus = true;
Service *s = SERVICE(u);
ServiceResult f;
+ ExitClean clean_mode;
assert(s);
assert(pid >= 0);
- if (is_clean_exit(code, status, s->type == SERVICE_ONESHOT ? EXIT_CLEAN_COMMAND : EXIT_CLEAN_DAEMON, &s->success_status))
+ /* Oneshot services and non-SERVICE_EXEC_START commands should not be
+ * considered daemons as they are typically not long running. */
+ if (s->type == SERVICE_ONESHOT || (s->control_pid == pid && s->control_command_id != SERVICE_EXEC_START))
+ clean_mode = EXIT_CLEAN_COMMAND;
+ else
+ clean_mode = EXIT_CLEAN_DAEMON;
+
+ if (is_clean_exit(code, status, clean_mode, &s->success_status))
f = SERVICE_SUCCESS;
else if (code == CLD_EXITED)
f = SERVICE_FAILURE_EXIT_CODE;