diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 9f65394b06..467b905f14 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -872,9 +872,8 @@
Takes one of , , ,
, , ,
, , and . In system mode,
- all options except and are allowed. In user mode, only
- , , and are allowed. Both options default
- to .
+ all options are allowed. In user mode, only , , and
+ are allowed. Both options default to .
If is set, no action will be triggered. causes a reboot
following the normal shutdown procedure (i.e. equivalent to systemctl reboot).
@@ -884,7 +883,7 @@
reboot2 system call, which
might result in data loss. Similarly, , ,
have the effect of powering down the system with similar
- semantics. causes the user manager to exit following the normal shutdown procedure, and
+ semantics. causes the manager to exit following the normal shutdown procedure, and
causes it terminate without shutting down services.
diff --git a/src/core/emergency-action.c b/src/core/emergency-action.c
index 3f0c11a3f2..e12ff81601 100644
--- a/src/core/emergency-action.c
+++ b/src/core/emergency-action.c
@@ -10,6 +10,7 @@
#include "special.h"
#include "string-table.h"
#include "terminal-util.h"
+#include "virt.h"
static void log_and_status(Manager *m, const char *message, const char *reason) {
log_warning("%s: %s", message, reason);
@@ -71,12 +72,14 @@ int emergency_action(
break;
case EMERGENCY_ACTION_EXIT:
- assert(MANAGER_IS_USER(m));
+ if (MANAGER_IS_USER(m) || detect_container() > 0) {
+ log_and_status(m, "Exiting", reason);
+ (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
+ break;
+ }
- log_and_status(m, "Exiting", reason);
-
- (void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL);
- break;
+ log_notice("Doing \"poweroff\" action instead of an \"exit\" emergency action.");
+ _fallthrough_;
case EMERGENCY_ACTION_POWEROFF:
log_and_status(m, "Powering off", reason);
@@ -84,11 +87,14 @@ int emergency_action(
break;
case EMERGENCY_ACTION_EXIT_FORCE:
- assert(MANAGER_IS_USER(m));
+ if (MANAGER_IS_USER(m) || detect_container() > 0) {
+ log_and_status(m, "Exiting immediately", reason);
+ m->objective = MANAGER_EXIT;
+ break;
+ }
- log_and_status(m, "Exiting immediately", reason);
- m->objective = MANAGER_EXIT;
- break;
+ log_notice("Doing \"poweroff-force\" action instead of an \"exit-force\" emergency action.");
+ _fallthrough_;
case EMERGENCY_ACTION_POWEROFF_FORCE:
log_and_status(m, "Forcibly powering off", reason);
@@ -135,8 +141,7 @@ int parse_emergency_action(
if (x < 0)
return -EINVAL;
- if ((system && x >= _EMERGENCY_ACTION_FIRST_USER_ACTION) ||
- (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION))
+ if (!system && x != EMERGENCY_ACTION_NONE && x < _EMERGENCY_ACTION_FIRST_USER_ACTION)
return -EOPNOTSUPP;
*ret = x;
diff --git a/src/test/test-emergency-action.c b/src/test/test-emergency-action.c
index 493b23227e..8ce28ed9f5 100644
--- a/src/test/test-emergency-action.c
+++ b/src/test/test-emergency-action.c
@@ -36,10 +36,10 @@ static void test_parse_emergency_action(void) {
assert_se(parse_emergency_action("poweroff-force", true, &x) == 0);
assert_se(x == EMERGENCY_ACTION_POWEROFF_FORCE);
assert_se(parse_emergency_action("poweroff-immediate", true, &x) == 0);
- assert_se(parse_emergency_action("exit", true, &x) == -EOPNOTSUPP);
- assert_se(parse_emergency_action("exit-force", true, &x) == -EOPNOTSUPP);
+ assert_se(parse_emergency_action("exit", true, &x) == 0);
+ assert_se(parse_emergency_action("exit-force", true, &x) == 0);
assert_se(parse_emergency_action("exit-forcee", true, &x) == -EINVAL);
- assert_se(x == EMERGENCY_ACTION_POWEROFF_IMMEDIATE);
+ assert_se(x == EMERGENCY_ACTION_EXIT_FORCE);
}
int main(int argc, char **argv) {
diff --git a/units/meson.build b/units/meson.build
index 9d372c78a8..3cc86b3e92 100644
--- a/units/meson.build
+++ b/units/meson.build
@@ -85,6 +85,7 @@ units = [
'multi-user.target.wants/'],
['systemd-coredump.socket', 'ENABLE_COREDUMP',
'sockets.target.wants/'],
+ ['systemd-exit.service', ''],
['systemd-initctl.socket', '',
'sockets.target.wants/'],
['systemd-journal-gatewayd.socket', 'ENABLE_REMOTE HAVE_MICROHTTPD'],
@@ -135,7 +136,6 @@ in_units = [
['systemd-binfmt.service', 'ENABLE_BINFMT',
'sysinit.target.wants/'],
['systemd-coredump@.service', 'ENABLE_COREDUMP'],
- ['systemd-exit.service', ''],
['systemd-firstboot.service', 'ENABLE_FIRSTBOOT',
'sysinit.target.wants/'],
['systemd-fsck-root.service', ''],
diff --git a/units/systemd-exit.service.in b/units/systemd-exit.service
similarity index 88%
rename from units/systemd-exit.service.in
rename to units/systemd-exit.service
index 2fb6ebd767..6029b13a05 100644
--- a/units/systemd-exit.service.in
+++ b/units/systemd-exit.service
@@ -13,7 +13,4 @@ Documentation=man:systemd.special(7)
DefaultDependencies=no
Requires=shutdown.target
After=shutdown.target
-
-[Service]
-Type=oneshot
-ExecStart=@SYSTEMCTL@ --force exit
+SuccessAction=exit