[EMERGENCY_ACTION_HALT_IMMEDIATE] = "halt-immediate",
};
-static void log_and_status(Manager *m, bool warn, const char *message, const char *reason) {
- log_full(warn ? LOG_WARNING : LOG_DEBUG, "%s: %s", message, reason);
- if (warn)
- manager_status_printf(m, STATUS_TYPE_EMERGENCY,
- ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
- "%s: %s", message, reason);
+static void log_and_status(
+ Manager *m,
+ EmergencyAction action,
+ EmergencyActionFlags flags,
+ const char *message,
+ const char *reason) {
+
+ assert(m);
+ assert(message);
+ assert(reason);
+
+ log_full(FLAGS_SET(flags, EMERGENCY_ACTION_WARN) ? LOG_WARNING : LOG_DEBUG,
+ "%s: %s", message, reason);
+
+ bool do_sleep = FLAGS_SET(flags, EMERGENCY_ACTION_WARN|EMERGENCY_ACTION_SLEEP_5S) &&
+ IN_SET(action,
+ EMERGENCY_ACTION_EXIT_FORCE,
+ EMERGENCY_ACTION_REBOOT_FORCE, EMERGENCY_ACTION_REBOOT_IMMEDIATE,
+ EMERGENCY_ACTION_POWEROFF_FORCE, EMERGENCY_ACTION_POWEROFF_IMMEDIATE,
+ EMERGENCY_ACTION_SOFT_REBOOT_FORCE,
+ EMERGENCY_ACTION_KEXEC_FORCE);
+
+ if (FLAGS_SET(flags, EMERGENCY_ACTION_WARN))
+ manager_status_printf(
+ m,
+ STATUS_TYPE_EMERGENCY,
+ ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL,
+ "%s: %s%s", message, reason,
+ do_sleep ? ", proceeding in 5s" : "");
+
+ /* Optionally sleep for 5s so that the user can see this output, before we actually execute the
+ * operation. Do this only if we immediately execute an operation, i.e. when there's no event loop to
+ * feed anymore. */
+ if (do_sleep)
+ (void) sleep(5);
}
void emergency_action(
Manager *m,
EmergencyAction action,
- EmergencyActionFlags options,
+ EmergencyActionFlags flags,
const char *reboot_arg,
int exit_status,
const char *reason) {
assert(m);
assert(action >= 0);
assert(action < _EMERGENCY_ACTION_MAX);
+ assert((flags & ~_EMERGENCY_ACTION_FLAGS_MAX) == 0);
+ assert(reason);
+
+ if (action == EMERGENCY_ACTION_NONE)
+ return;
/* Is the special shutdown target active or queued? If so, we are in shutdown state */
if (IN_SET(action,
}
}
- if (action == EMERGENCY_ACTION_NONE)
- return;
-
- if (FLAGS_SET(options, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) {
+ if (FLAGS_SET(flags, EMERGENCY_ACTION_IS_WATCHDOG) && !m->service_watchdogs) {
log_warning("Watchdog disabled! Not acting on: %s", reason);
return;
}
- bool warn = FLAGS_SET(options, EMERGENCY_ACTION_WARN);
-
switch (action) {
case EMERGENCY_ACTION_REBOOT:
- log_and_status(m, warn, "Rebooting", reason);
+ log_and_status(m, action, flags, "Rebooting", reason);
(void) update_reboot_parameter_and_warn(reboot_arg, true);
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
break;
case EMERGENCY_ACTION_REBOOT_FORCE:
- log_and_status(m, warn, "Forcibly rebooting", reason);
+ log_and_status(m, action, flags, "Forcibly rebooting", reason);
(void) update_reboot_parameter_and_warn(reboot_arg, true);
m->objective = MANAGER_REBOOT;
break;
case EMERGENCY_ACTION_REBOOT_IMMEDIATE:
- log_and_status(m, warn, "Rebooting immediately", reason);
+ log_and_status(m, action, flags, "Rebooting immediately", reason);
sync();
break;
case EMERGENCY_ACTION_SOFT_REBOOT:
- log_and_status(m, warn, "Soft-rebooting", reason);
+ log_and_status(m, action, flags, "Soft-rebooting", reason);
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
break;
case EMERGENCY_ACTION_SOFT_REBOOT_FORCE:
- log_and_status(m, warn, "Forcibly soft-rebooting", reason);
+ log_and_status(m, action, flags, "Forcibly soft-rebooting", reason);
m->objective = MANAGER_SOFT_REBOOT;
break;
m->return_value = exit_status;
if (MANAGER_IS_USER(m) || detect_container() > 0) {
- log_and_status(m, warn, "Exiting", reason);
+ log_and_status(m, action, flags, "Exiting", reason);
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_EXIT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
break;
}
_fallthrough_;
case EMERGENCY_ACTION_POWEROFF:
- log_and_status(m, warn, "Powering off", reason);
+ log_and_status(m, action, flags, "Powering off", reason);
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
break;
m->return_value = exit_status;
if (MANAGER_IS_USER(m) || detect_container() > 0) {
- log_and_status(m, warn, "Exiting immediately", reason);
+ log_and_status(m, action, flags, "Exiting immediately", reason);
m->objective = MANAGER_EXIT;
break;
}
_fallthrough_;
case EMERGENCY_ACTION_POWEROFF_FORCE:
- log_and_status(m, warn, "Forcibly powering off", reason);
+ log_and_status(m, action, flags, "Forcibly powering off", reason);
m->objective = MANAGER_POWEROFF;
break;
case EMERGENCY_ACTION_POWEROFF_IMMEDIATE:
- log_and_status(m, warn, "Powering off immediately", reason);
+ log_and_status(m, action, flags, "Powering off immediately", reason);
sync();
break;
case EMERGENCY_ACTION_KEXEC:
- log_and_status(m, warn, "Executing kexec", reason);
+ log_and_status(m, action, flags, "Executing kexec", reason);
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
break;
case EMERGENCY_ACTION_KEXEC_FORCE:
- log_and_status(m, warn, "Forcibly executing kexec", reason);
+ log_and_status(m, action, flags, "Forcibly executing kexec", reason);
m->objective = MANAGER_KEXEC;
break;
case EMERGENCY_ACTION_HALT:
- log_and_status(m, warn, "Halting", reason);
+ log_and_status(m, action, flags, "Halting", reason);
(void) manager_add_job_by_name_and_warn(m, JOB_START, SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY, NULL, NULL);
break;
case EMERGENCY_ACTION_HALT_FORCE:
- log_and_status(m, warn, "Forcibly halting", reason);
+ log_and_status(m, action, flags, "Forcibly halting", reason);
m->objective = MANAGER_HALT;
break;
case EMERGENCY_ACTION_HALT_IMMEDIATE:
- log_and_status(m, warn, "Halting immediately", reason);
+ log_and_status(m, action, flags, "Halting immediately", reason);
sync();