]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pid1,systemctl: allow symbolic exit code names
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Sun, 28 Jul 2019 10:37:31 +0000 (12:37 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 29 Jul 2019 13:54:53 +0000 (15:54 +0200)
TODO
man/systemd.service.xml
src/core/load-fragment.c
src/shared/bus-unit-util.c

diff --git a/TODO b/TODO
index af41aa57acd84b1f14e9856d1cbbeaec7707e690..ae52d9fc3bed5879b296637ca1c05c4cba34cfec 100644 (file)
--- a/TODO
+++ b/TODO
@@ -220,9 +220,6 @@ Features:
 
 * add --vacuum-xyz options to coredumpctl, matching those journalctl already has.
 
-* SuccessExitStatus= and friends should probably also accept symbolic exit
-  codes names, i.e. error codes from the list maintained in exit-codes.[ch]
-
 * introduce Ephemeral= unit file switch, that creates an ephemeral copy of all
   files and directories that are left writable for a unit, and which are
   removed after the unit goes down again. A bit like --ephemeral for
index 90c1257f37eadb68a380408195f0ac6376727c10..06116df1b035d29ab30dda65c79cb8e83605b6a5 100644 (file)
 
       <varlistentry>
         <term><varname>SuccessExitStatus=</varname></term>
-        <listitem><para>Takes a list of exit status definitions that,
-        when returned by the main service process, will be considered
-        successful termination, in addition to the normal successful
-        exit code 0 and the signals <constant>SIGHUP</constant>,
-        <constant>SIGINT</constant>, <constant>SIGTERM</constant>, and
-        <constant>SIGPIPE</constant>. Exit status definitions can
-        either be numeric exit codes or termination signal names,
-        separated by spaces. For example:
-
-        <programlisting>SuccessExitStatus=1 2 8 SIGKILL</programlisting>
-
-        ensures that exit codes 1, 2, 8 and
-        the termination signal <constant>SIGKILL</constant> are
-        considered clean service terminations.
-        </para>
+        <listitem><para>Takes a list of exit status definitions that, when returned by the main service
+        process, will be considered successful termination, in addition to the normal successful exit code 0
+        and the signals <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
+        <constant>SIGTERM</constant>, and <constant>SIGPIPE</constant>. Exit status definitions can be
+        numeric exit codes, termination code names, or termination signal names, separated by spaces. See the
+        Process Exit Codes section in
+        <citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
+        a list of termination codes names (for this setting only the part without the
+        <literal>EXIT_</literal> or <literal>EX_</literal> prefix should be used). See
+        <citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
+        a list of signal names.</para>
 
         <para>This option may appear more than once, in which case the
         list of successful exit statuses is merged. If the empty
         string is assigned to this option, the list is reset, all
         prior assignments of this option will have no
-        effect.</para></listitem>
+        effect.</para>
+
+        <example>
+          <title>A service with with the the <varname>SuccessExitStatus=</varname> setting</title>
+
+          <programlisting>SuccessExitStatus=TEMPFAIL 250 SIGUSR1</programlisting>
+
+          <para>Exit codes 75 (<constant>TEMPFAIL</constant>), 250, and the termination signal
+          <constant>SIGKILL</constant> are considered clean service terminations.</para>
+        </example></listitem>
       </varlistentry>
 
       <varlistentry>
index ecea4f526a4d2444526d63cd7d331b5018c7965a..8664500e1d317c10d93a0f0f6463cd50be9e0999 100644 (file)
@@ -3936,33 +3936,33 @@ int config_parse_set_status(
 
         FOREACH_WORD(word, l, rvalue, state) {
                 _cleanup_free_ char *temp;
-                int val;
                 Bitmap *bitmap;
 
                 temp = strndup(word, l);
                 if (!temp)
                         return log_oom();
 
-                r = safe_atoi(temp, &val);
-                if (r < 0) {
-                        val = signal_from_string(temp);
+                /* We need to call exit_status_from_string() first, because we want
+                 * to parse numbers as exit statuses, not signals. */
 
-                        if (val <= 0) {
-                                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse value, ignoring: %s", word);
-                                continue;
-                        }
-                        bitmap = &status_set->signal;
+                r = exit_status_from_string(temp);
+                if (r >= 0) {
+                        assert(r >= 0 && r < 256);
+                        bitmap = &status_set->status;
                 } else {
-                        if (val < 0 || val > 255) {
-                                log_syntax(unit, LOG_ERR, filename, line, 0, "Value %d is outside range 0-255, ignoring", val);
+                        r = signal_from_string(temp);
+
+                        if (r <= 0) {
+                                log_syntax(unit, LOG_ERR, filename, line, 0,
+                                           "Failed to parse value, ignoring: %s", word);
                                 continue;
                         }
-                        bitmap = &status_set->status;
+                        bitmap = &status_set->signal;
                 }
 
-                r = bitmap_set(bitmap, val);
+                r = bitmap_set(bitmap, r);
                 if (r < 0)
-                        return log_oom();
+                        return log_error_errno(r, "Failed to set signal or status %s: %m", word);
         }
         if (!isempty(state))
                 log_syntax(unit, LOG_ERR, filename, line, 0, "Trailing garbage, ignoring.");
index 99511d338aa521bd00d8225b30bce20eeeaaac7f..e53b9d5ea29c36f630e89496395c4327969856cd 100644 (file)
@@ -10,6 +10,7 @@
 #include "cpu-set-util.h"
 #include "escape.h"
 #include "exec-util.h"
+#include "exit-status.h"
 #include "hexdecoct.h"
 #include "hostname-util.h"
 #include "in-addr-util.h"
@@ -1444,7 +1445,6 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
 
                 for (p = eq;;) {
                         _cleanup_free_ char *word = NULL;
-                        int val;
 
                         r = extract_first_word(&p, &word, NULL, EXTRACT_UNQUOTE);
                         if (r == 0)
@@ -1454,24 +1454,30 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
                         if (r < 0)
                                 return log_error_errno(r, "Invalid syntax in %s: %s", field, eq);
 
-                        r = safe_atoi(word, &val);
-                        if (r < 0) {
-                                val = signal_from_string(word);
-                                if (val < 0)
-                                        return log_error_errno(r, "Invalid status or signal %s in %s: %m", word, field);
+                        /* We need to call exit_status_from_string() first, because we want
+                         * to parse numbers as exit statuses, not signals. */
 
-                                signal = reallocarray(signal, n_signal + 1, sizeof(int));
-                                if (!signal)
-                                        return log_oom();
+                        r = exit_status_from_string(word);
+                        if (r >= 0) {
+                                assert(r >= 0 && r < 256);
 
-                                signal[n_signal++] = val;
-                        } else {
                                 status = reallocarray(status, n_status + 1, sizeof(int));
                                 if (!status)
                                         return log_oom();
 
-                                status[n_status++] = val;
-                        }
+                                status[n_status++] = r;
+
+                        } else if ((r = signal_from_string(word)) >= 0) {
+                                signal = reallocarray(signal, n_signal + 1, sizeof(int));
+                                if (!signal)
+                                        return log_oom();
+
+                                signal[n_signal++] = r;
+
+                        } else
+                                /* original r from exit_status_to_string() */
+                                return log_error_errno(r, "Invalid status or signal %s in %s: %m",
+                                                       word, field);
                 }
 
                 r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");