[systemd-devel] [PATCH] Add support for supplying an exit status code to "systemctl exit"

Vito Caputo vito.caputo at coreos.com
Thu Nov 6 18:09:38 PST 2014


The capability of directly propagating a return code out to the caller of
systemd --user from within something like an OnFailure unit has utility.

This also contains a minor fixup to the documentation adding "exit" to the
--force section.

Cheers,
Vito Caputo

---
 man/systemctl.xml         | 11 ++++++-----
 src/core/dbus-manager.c   |  6 +++++-
 src/core/main.c           |  2 +-
 src/core/manager.c        |  1 +
 src/core/manager.h        |  1 +
 src/systemctl/systemctl.c | 20 ++++++++++++++++++--
 6 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 7cbaa6c..25ad2f7 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -432,9 +432,9 @@ along with systemd; If not, see <
http://www.gnu.org/licenses/>.
           <para>When used with <command>enable</command>, overwrite
           any existing conflicting symlinks.</para>

-          <para>When used with <command>halt</command>,
-          <command>poweroff</command>, <command>reboot</command> or
-          <command>kexec</command>, execute the selected operation
+         <para>When used with <command>exit</command>,
<command>halt</command>,
+         <command>poweroff</command>, <command>reboot</command> or
+         <command>kexec</command>, execute the selected operation
           without shutting down all units. However, all processes will
           be killed forcibly and all file systems are unmounted or
           remounted read-only. This is hence a drastic but relatively
@@ -1485,13 +1485,14 @@ kobject-uevent 1 systemd-udevd-kernel.socket
systemd-udevd.service
           </listitem>
         </varlistentry>
         <varlistentry>
-          <term><command>exit</command></term>
+          <term><command>exit
<optional><replaceable>STATUS</replaceable></optional></command></term>

           <listitem>
             <para>Ask the systemd manager to quit. This is only
             supported for user service managers (i.e. in conjunction
             with the <option>--user</option> option) and will fail
-            otherwise.</para>
+            otherwise.  Used in conjunction with --force a status code may
be
+           propagated into the sytemd manager's exit code.</para>
           </listitem>

         </varlistentry>
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index c54abd3..78f7f6d 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1140,6 +1140,10 @@ static int method_exit(sd_bus *bus, sd_bus_message
*message, void *userdata, sd_
         if (m->running_as == SYSTEMD_SYSTEM)
                 return sd_bus_error_setf(error,
SD_BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service
managers.");

+        r = sd_bus_message_read(message, "i", &m->exit_retval);
+        if (r < 0)
+                return r;
+
         m->exit_code = MANAGER_EXIT;

         return sd_bus_reply_method_return(message, NULL);
@@ -1918,7 +1922,7 @@ const sd_bus_vtable bus_manager_vtable[] = {
         SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot,
0),
         SD_BUS_METHOD("Reload", NULL, NULL, method_reload,
SD_BUS_VTABLE_UNPRIVILEGED),
         SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute,
SD_BUS_VTABLE_UNPRIVILEGED),
-        SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0),
+        SD_BUS_METHOD("Exit", "i", NULL, method_exit, 0),
         SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot,
SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
         SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff,
SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
         SD_BUS_METHOD("Halt", NULL, NULL, method_halt,
SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)),
diff --git a/src/core/main.c b/src/core/main.c
index d48604e..2481f5c 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1737,7 +1737,7 @@ int main(int argc, char *argv[]) {
                 switch (m->exit_code) {

                 case MANAGER_EXIT:
-                        retval = EXIT_SUCCESS;
+                        retval = m->exit_retval;
                         log_debug("Exit.");
                         goto finish;

diff --git a/src/core/manager.c b/src/core/manager.c
index 129f6dd..e417514 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -550,6 +550,7 @@ int manager_new(SystemdRunningAs running_as, bool
test_run, Manager **_m) {

         m->running_as = running_as;
         m->exit_code = _MANAGER_EXIT_CODE_INVALID;
+        m->exit_retval = EXIT_SUCCESS;
         m->default_timer_accuracy_usec = USEC_PER_MINUTE;

         m->idle_pipe[0] = m->idle_pipe[1] = m->idle_pipe[2] =
m->idle_pipe[3] = -1;
diff --git a/src/core/manager.h b/src/core/manager.h
index ab72548..ef96e03 100644
--- a/src/core/manager.h
+++ b/src/core/manager.h
@@ -232,6 +232,7 @@ struct Manager {
         /* Flags */
         SystemdRunningAs running_as;
         ManagerExitCode exit_code:5;
+        int exit_retval;

         bool dispatching_load_queue:1;
         bool dispatching_dbus_queue:1;
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index d9e9c2a..11c7e55 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -4875,6 +4875,22 @@ static int daemon_reload(sd_bus *bus, char **args) {
         if (r < 0)
                 return bus_log_create_error(r);

+        if (streq(method, "Exit")) {
+                int retval = EXIT_SUCCESS;
+
+                if (strv_length(args) > 1) {
+                        r = safe_atoi(args[1], &retval);
+                        if (r < 0) {
+                                log_error("Invalid exit status: %s",
strerror(-r));
+                                return -EINVAL;
+                        }
+                }
+
+                r = sd_bus_message_append(m, "i", retval);
+                if (r < 0)
+                        return bus_log_create_error(r);
+        }
+
         r = sd_bus_message_set_allow_interactive_authorization(m,
arg_ask_password);
         if (r < 0)
                 return bus_log_create_error(r);
@@ -5849,7 +5865,7 @@ static void systemctl_help(void) {
                "  poweroff                        Shut down and power-off
the system\n"
                "  reboot [ARG]                    Shut down and reboot the
system\n"
                "  kexec                           Shut down and reboot the
system with kexec\n"
-               "  exit                            Request user instance
exit\n"
+               "  exit [STATUS]                   Request user instance
exit\n"
                "  switch-root ROOT [INIT]         Change to a different
root file system\n"
                "  suspend                         Suspend the system\n"
                "  hibernate                       Hibernate the system\n"
@@ -6815,7 +6831,7 @@ static int systemctl_main(sd_bus *bus, int argc, char
*argv[], int bus_error) {
                 { "default",               EQUAL, 1, start_special     },
                 { "rescue",                EQUAL, 1, start_special     },
                 { "emergency",             EQUAL, 1, start_special     },
-                { "exit",                  EQUAL, 1, start_special     },
+                { "exit",                  LESS,  2, start_special     },
                 { "reset-failed",          MORE,  1, reset_failed      },
                 { "enable",                MORE,  2, enable_unit,
NOBUS },
                 { "disable",               MORE,  2, enable_unit,
NOBUS },
--
2.1.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/systemd-devel/attachments/20141106/273860ca/attachment-0001.html>


More information about the systemd-devel mailing list