summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2016-10-10 22:07:30 +0200
committerLennart Poettering <lennart@poettering.net>2016-10-10 22:57:01 +0200
commit1f0958f640b87175cd547c1e69084cfe54a22e9d (patch)
treee1a49f2a31920394f951f3d14f0e7e06125faab5
parent38107f5a4ad5ab148054910040d5d548a4c7a805 (diff)
core: when determining whether a process exit status is clean, consider whether it is a command or a daemon
SIGTERM should be considered a clean exit code for daemons (i.e. long-running processes, as a daemon without SIGTERM handler may be shut down without issues via SIGTERM still) while it should not be considered a clean exit code for commands (i.e. short-running processes). Let's add two different clean checking modes for this, and use the right one at the appropriate places. Fixes: #4275
-rw-r--r--src/basic/exit-status.c8
-rw-r--r--src/basic/exit-status.h7
-rw-r--r--src/core/busname.c2
-rw-r--r--src/core/mount.c2
-rw-r--r--src/core/service.c2
-rw-r--r--src/core/socket.c2
-rw-r--r--src/core/swap.c2
-rw-r--r--src/remount-fs/remount-fs.c2
-rw-r--r--src/systemctl/systemctl.c2
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c2
10 files changed, 18 insertions, 13 deletions
diff --git a/src/basic/exit-status.c b/src/basic/exit-status.c
index 96d4619da6..59557f8afe 100644
--- a/src/basic/exit-status.c
+++ b/src/basic/exit-status.c
@@ -177,17 +177,17 @@ const char* exit_status_to_string(int status, ExitStatusLevel level) {
return NULL;
}
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
if (code == CLD_EXITED)
return status == 0 ||
(success_status &&
set_contains(success_status->status, INT_TO_PTR(status)));
- /* If a daemon does not implement handlers for some of the
- * signals that's not considered an unclean shutdown */
+ /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
if (code == CLD_KILLED)
- return IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE) ||
+ return
+ (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
(success_status &&
set_contains(success_status->signal, INT_TO_PTR(status)));
diff --git a/src/basic/exit-status.h b/src/basic/exit-status.h
index b3baa50cf4..0cfdfd7891 100644
--- a/src/basic/exit-status.h
+++ b/src/basic/exit-status.h
@@ -98,7 +98,12 @@ typedef struct ExitStatusSet {
const char* exit_status_to_string(int status, ExitStatusLevel level) _const_;
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status);
+typedef enum ExitClean {
+ EXIT_CLEAN_DAEMON,
+ EXIT_CLEAN_COMMAND,
+} ExitClean;
+
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status);
void exit_status_set_free(ExitStatusSet *x);
bool exit_status_set_is_empty(ExitStatusSet *x);
diff --git a/src/core/busname.c b/src/core/busname.c
index 7952cd31aa..a69e3831f6 100644
--- a/src/core/busname.c
+++ b/src/core/busname.c
@@ -868,7 +868,7 @@ static void busname_sigchld_event(Unit *u, pid_t pid, int code, int status) {
n->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = BUSNAME_SUCCESS;
else if (code == CLD_EXITED)
f = BUSNAME_FAILURE_EXIT_CODE;
diff --git a/src/core/mount.c b/src/core/mount.c
index 04025b83b9..ed542776ac 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1159,7 +1159,7 @@ static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) {
m->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = MOUNT_SUCCESS;
else if (code == CLD_EXITED)
f = MOUNT_FAILURE_EXIT_CODE;
diff --git a/src/core/service.c b/src/core/service.c
index fc1d353356..98edc437a2 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -2600,7 +2600,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
assert(s);
assert(pid >= 0);
- if (is_clean_exit(code, status, &s->success_status))
+ if (is_clean_exit(code, status, s->type == SERVICE_ONESHOT ? EXIT_CLEAN_COMMAND : EXIT_CLEAN_DAEMON, &s->success_status))
f = SERVICE_SUCCESS;
else if (code == CLD_EXITED)
f = SERVICE_FAILURE_EXIT_CODE;
diff --git a/src/core/socket.c b/src/core/socket.c
index b9032fa5c9..1b4a1b3dc3 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2743,7 +2743,7 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = SOCKET_SUCCESS;
else if (code == CLD_EXITED)
f = SOCKET_FAILURE_EXIT_CODE;
diff --git a/src/core/swap.c b/src/core/swap.c
index fb222b6858..fee9e7b0e6 100644
--- a/src/core/swap.c
+++ b/src/core/swap.c
@@ -988,7 +988,7 @@ static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) {
s->control_pid = 0;
- if (is_clean_exit(code, status, NULL))
+ if (is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL))
f = SWAP_SUCCESS;
else if (code == CLD_EXITED)
f = SWAP_FAILURE_EXIT_CODE;
diff --git a/src/remount-fs/remount-fs.c b/src/remount-fs/remount-fs.c
index 6468d1eecd..c3bdcaf1da 100644
--- a/src/remount-fs/remount-fs.c
+++ b/src/remount-fs/remount-fs.c
@@ -137,7 +137,7 @@ int main(int argc, char *argv[]) {
s = hashmap_remove(pids, PID_TO_PTR(si.si_pid));
if (s) {
- if (!is_clean_exit(si.si_code, si.si_status, NULL)) {
+ if (!is_clean_exit(si.si_code, si.si_status, EXIT_CLEAN_COMMAND, NULL)) {
if (si.si_code == CLD_EXITED)
log_error(MOUNT_PATH " for %s exited with exit status %i.", s, si.si_status);
else
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 9c6a475a39..18a8a4f248 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3936,7 +3936,7 @@ static void print_status_info(
argv = strv_join(p->argv, " ");
printf(" Process: "PID_FMT" %s=%s ", p->pid, p->name, strna(argv));
- good = is_clean_exit(p->code, p->status, NULL);
+ good = is_clean_exit(p->code, p->status, EXIT_CLEAN_DAEMON, NULL);
if (!good) {
on = ansi_highlight_red();
off = ansi_normal();
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 8851af449d..b45490be1a 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -827,7 +827,7 @@ static int ask_on_consoles(int argc, char *argv[]) {
break;
}
- if (!is_clean_exit(status.si_code, status.si_status, NULL))
+ if (!is_clean_exit(status.si_code, status.si_status, EXIT_CLEAN_DAEMON, NULL))
log_error("Password agent failed with: %d", status.si_status);
terminate_agents(pids);