]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
run: propagate return code/status from the child 13868/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 29 Oct 2019 17:07:07 +0000 (18:07 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 5 Nov 2019 20:38:21 +0000 (21:38 +0100)
Fixes #13756. We were returning things that didn't make much sense:
we would always use the exit_code value as the exit code. But it sometimes
contains a exit code from the process, and sometimes the number of a signal
that was used to kill the process. We would also ignore SuccessExitStatus=
and in general whether systemd thinks the service exited successfully
(hence the issue in #13756, where systemd would return success/SIGTERM,
but we'd just look at the SIGTERM part.)

If we are doing --wait, let's always propagate the exit code/status from
the child.

While at it, make the documentation useful.

man/systemd-run.xml
src/run/run.c

index 610c3acd37c2ef840b6c151f66a423340a5ddc15..3a1d18dae9ad7b3f7c5e15e67d46bf8f88bc2fec 100644 (file)
   <refsect1>
     <title>Exit status</title>
 
-    <para>On success, 0 is returned, a non-zero failure
-    code otherwise.</para>
+    <para>On success, 0 is returned. If <command>systemd-run</command> failed to start the service, a
+    non-zero return value will be returned. If <command>systemd-run</command> waits for the service to
+    terminate, the return value will be propagated from the service. 0 will be returned on success, including
+    all the cases where systemd considers a service to have exited cleanly, see the discussion of
+    <varname>SuccessExitStatus=</varname> in
+    <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    </para>
   </refsect1>
 
   <refsect1>
@@ -503,6 +508,16 @@ There is a screen on:
 
       <programlisting>$ loginctl enable-linger</programlisting>
     </example>
+
+    <example>
+      <title>Return value</title>
+
+      <programlisting>$ systemd-run --user --wait true
+$ systemd-run --user --wait -p SuccessExitStatus=11 bash -c 'exit 11'
+$ systemd-run --user --wait -p SuccessExitStatus=SIGUSR1 bash -c 'kill -SIGUSR1 $$$$'</programlisting>
+
+      <para>Those three invocations will succeed, i.e. terminate with an exit code of 0.</para>
+    </example>
   </refsect1>
 
   <refsect1>
index 3d63cf0254035eb70b9f56eaf0d914e490c7503e..de968caf3f8fb2328a01f268a33f1c12d9e146dd 100644 (file)
@@ -16,6 +16,7 @@
 #include "bus-wait-for-jobs.h"
 #include "calendarspec.h"
 #include "env-util.h"
+#include "exit-status.h"
 #include "fd-util.h"
 #include "format-util.h"
 #include "main-func.h"
@@ -1303,9 +1304,14 @@ static int start_transient_service(
                         }
                 }
 
-                /* Try to propagate the service's return value */
-                if (c.result && STR_IN_SET(c.result, "success", "exit-code") && c.exit_code == CLD_EXITED)
+                /* Try to propagate the service's return value. But if the service defines
+                 * e.g. SuccessExitStatus, honour this, and return 0 to mean "success". */
+                if (streq_ptr(c.result, "success"))
+                        *retval = 0;
+                else if (streq_ptr(c.result, "exit-code") && c.exit_status > 0)
                         *retval = c.exit_status;
+                else if (streq_ptr(c.result, "signal"))
+                        *retval = EXIT_EXCEPTION;
                 else
                         *retval = EXIT_FAILURE;
         }