]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: when determining whether a process exit status is clean, consider whether it...
authorLennart Poettering <lennart@poettering.net>
Mon, 10 Oct 2016 20:07:30 +0000 (22:07 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 10 Oct 2016 20:57:01 +0000 (22:57 +0200)
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
src/basic/exit-status.c
src/basic/exit-status.h
src/core/busname.c
src/core/mount.c
src/core/service.c
src/core/socket.c
src/core/swap.c
src/remount-fs/remount-fs.c
src/systemctl/systemctl.c
src/tty-ask-password-agent/tty-ask-password-agent.c

index 96d4619da6d0b3b03eb7a504d35cab8b10c31f1f..59557f8afea2cf2816d7389b283816de5c297dc8 100644 (file)
@@ -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)));
 
index b3baa50cf44eaeaff0835483a28456f764f5a34c..0cfdfd789199427ff495efdebe5e70f2eef503af 100644 (file)
@@ -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);
index 7952cd31aad1c948a3d0fb2cef16627c912d4171..a69e3831f695ebcd8f2d259c7d8e700dc7209372 100644 (file)
@@ -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;
index 04025b83b9f280aa0f1e8fbe73589b0aaf1979fa..ed542776accbb4805dfead44d77dc6708ccd6434 100644 (file)
@@ -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;
index fc1d35335608a77348911a5c442bfcb755cc94d7..98edc437a2013f127b3858d70956ace8f5de91de 100644 (file)
@@ -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;
index b9032fa5c96ef01efd2e3980177b7b36f5016cf0..1b4a1b3dc32d93d2db24d2cc070a892934e53d13 100644 (file)
@@ -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;
index fb222b6858ecc5b7ae8a5296b6bba4535f09af9b..fee9e7b0e6d7c1b257ebdf4ceb6339ffc1b8b851 100644 (file)
@@ -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;
index 6468d1eecdb187799e74df00509871538e9fef48..c3bdcaf1da0eaabefed173b500a1963821ff9996 100644 (file)
@@ -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
index 9c6a475a3985cb7284ce5a03f18d49e3073d5cec..18a8a4f248d415f9d2b81f7874ddbef43472f95a 100644 (file)
@@ -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();
index 8851af449dc90678c9bcd6be9eb6a1fc2409e8c1..b45490be1ac39868cb370f3034c670973e4d9e61 100644 (file)
@@ -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);