summaryrefslogtreecommitdiff
path: root/src/systemctl
diff options
context:
space:
mode:
authorAlban Crequy <alban.crequy@gmail.com>2015-09-18 13:37:34 +0200
committerAlban Crequy <alban.crequy@gmail.com>2015-09-21 17:32:45 +0200
commit287419c119ef961db487a281162ab037eba70c61 (patch)
treee7f4c01e50b7b944b9d9d0ed8290ead8762da906 /src/systemctl
parenta1b7a5bbdd8da94e41b5e79be7a6e853ae910d2b (diff)
containers: systemd exits with non-zero code
When a systemd service running in a container exits with a non-zero code, it can be useful to terminate the container immediately and get the exit code back to the host, when systemd-nspawn returns. This was not possible to do. This patch adds the following to make it possible: - Add a read-only "ExitCode" property on PID 1's "Manager" bus object. By default, it is 0 so the behaviour stays the same as previously. - Add a method "SetExitCode" on the same object. The method fails when called on baremetal: it is only allowed in containers or in user session. - Add support in systemctl to call "systemctl exit 42". It reuses the existing code for user session. - Add exit.target and systemd-exit.service to the system instance. - Change main() to actually call systemd-shutdown to exit() with the correct value. - Add verb 'exit' in systemd-shutdown with parameter --exit-code - Update systemctl manpage. I used the following to test it: | $ sudo rkt --debug --insecure-skip-verify run \ | --mds-register=false --local docker://busybox \ | --exec=/bin/chroot -- /proc/1/root \ | systemctl --force exit 42 | ... | Container rkt-895a0cba-5c66-4fa5-831c-e3f8ddc5810d failed with error code 42. | $ echo $? | 42 Fixes https://github.com/systemd/systemd/issues/1290
Diffstat (limited to 'src/systemctl')
-rw-r--r--src/systemctl/systemctl.c30
1 files changed, 28 insertions, 2 deletions
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index d1e443b8a6..e20fc1bbbb 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -3005,6 +3005,7 @@ static int prepare_firmware_setup(sd_bus *bus) {
}
static int start_special(sd_bus *bus, char **args) {
+ _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
enum action a;
int r;
@@ -3029,6 +3030,31 @@ static int start_special(sd_bus *bus, char **args) {
r = update_reboot_param_file(args[1]);
if (r < 0)
return r;
+ } else if (a == ACTION_EXIT && strv_length(args) > 1) {
+ /* If the exit code is not given on the command line, don't
+ * reset it to zero: just keep it as it might have been set
+ * previously. */
+ uint8_t code = 0;
+
+ r = safe_atou8(args[1], &code);
+ if (r < 0) {
+ log_error("Invalid exit code.");
+ return -EINVAL;
+ }
+
+ r = sd_bus_call_method(
+ bus,
+ "org.freedesktop.systemd1",
+ "/org/freedesktop/systemd1",
+ "org.freedesktop.systemd1.Manager",
+ "SetExitCode",
+ &error,
+ NULL,
+ "y", code);
+ if (r < 0) {
+ log_error("Failed to execute operation: %s", bus_error_message(&error, r));
+ return r;
+ }
}
if (arg_force >= 2 &&
@@ -6224,7 +6250,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 [EXIT_CODE] Request user instance or container exit\n"
" switch-root ROOT [INIT] Change to a different root file system\n"
" suspend Suspend the system\n"
" hibernate Hibernate the system\n"
@@ -7211,7 +7237,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 },