summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-07-28 12:37:31 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-07-29 15:54:53 +0200
commit2e2ed88062fcd4fbe138a5198a979ccdea4fb11c (patch)
tree00640d95bae9468df9d07003059a8570953f69a5
parent62b21e2e89b68f0a1fb209e6677c61fdb4c32b34 (diff)
downloadsystemd-2e2ed88062fcd4fbe138a5198a979ccdea4fb11c.tar.gz
pid1,systemctl: allow symbolic exit code names
-rw-r--r--TODO3
-rw-r--r--man/systemd.service.xml37
-rw-r--r--src/core/load-fragment.c28
-rw-r--r--src/shared/bus-unit-util.c32
4 files changed, 54 insertions, 46 deletions
diff --git a/TODO b/TODO
index af41aa57ac..ae52d9fc3b 100644
--- 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
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 90c1257f37..06116df1b0 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -852,27 +852,32 @@
<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>
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index ecea4f526a..8664500e1d 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -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.");
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 99511d338a..e53b9d5ea2 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -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");