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
_______________________________________________ systemd-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/systemd-devel
