shutdown: enforce a minimum uptime to make boot loops less annoying

Fixes: #9453
This commit is contained in:
Lennart Poettering
2026-04-04 22:52:58 +02:00
parent 8cfae74dcd
commit 0874eea302
6 changed files with 82 additions and 0 deletions
+36
View File
@@ -51,6 +51,7 @@
#define SYNC_PROGRESS_ATTEMPTS 3
#define SYNC_TIMEOUT_USEC (10*USEC_PER_SEC)
#define DEFAULT_MINIMUM_UPTIME_USEC (15U * USEC_PER_SEC)
static const char *arg_verb = NULL;
static uint8_t arg_exit_code = 0;
@@ -343,6 +344,35 @@ static void notify_supervisor(void) {
arg_exit_code, arg_verb);
}
static void sleep_until_minimum_uptime(void) {
uint64_t minimum_uptime_usec = DEFAULT_MINIMUM_UPTIME_USEC;
int r;
const char *e = secure_getenv("MINIMUM_UPTIME_USEC");
if (e) {
r = safe_atou64(e, &minimum_uptime_usec);
if (r < 0)
log_warning_errno(r, "Failed to parse $MINIMUM_UPTIME_USEC, ignoring: %s", e);
}
if (minimum_uptime_usec <= 0) /* turned off? */
return;
for (;;) {
usec_t n = now(CLOCK_BOOTTIME);
if (n >= minimum_uptime_usec)
break;
usec_t m = minimum_uptime_usec - n;
log_notice("Delaying shutdown for %s, in order to reach minimum uptime of %s.",
FORMAT_TIMESPAN(m, USEC_PER_SEC),
FORMAT_TIMESPAN(minimum_uptime_usec, USEC_PER_SEC));
/* Sleep for up to 3s, then show message again, as a progress indicator. */
usleep_safe(MIN(m, 3 * USEC_PER_SEC));
}
}
int main(int argc, char *argv[]) {
static const char* const dirs[] = {
SYSTEM_SHUTDOWN_PATH,
@@ -611,6 +641,12 @@ int main(int argc, char *argv[]) {
notify_supervisor();
/* Enforce the minimum uptime, but don't bother with it in containers, since – unlike on bare metal
* and VMs – the screen output isn't flushed out immediately when we reboot (as OVMF or real PC
* firmwares do) */
if (!in_container)
sleep_until_minimum_uptime();
if (streq(arg_verb, "exit")) {
if (in_container) {
log_info("Exiting container.");