12.2 The Graceful Sequence

12.2.1 Step 1: Enter the shutdown state #

peinit sets an internal flag. While it is set, no new service starts, and control commands other than status, list and operation-status are rejected as invalid for the current state.

Timer triggers are not disarmed. A calendar timer that fires during the shutdown window is still classified and acted on: for a service in Inactive, Completed or Failed — precisely the states step 3 classifies as not participating — that means creating a start operation and starting the service. The shutdown plan was fixed when the shutdown began, so a service started this way is in no wave, is not waited for, and is not reached by the global-timeout sweep.

12.2.2 Step 2: Suspend Critical failure semantics #

A Critical service failing during shutdown is recorded but does not trigger a reboot. The system is already going down, and rebooting from here would loop.

12.2.3 Step 3: Classify #

Completed services — Oneshots with RemainAfterExit — have no process and are transitioned to Inactive, releasing the dependency relationships they were holding so their dependents can be stopped cleanly.

The rest are classified for stop eligibility:

  • Active and Reloading are graceful-stop eligible and enter the waves.
  • Stopping services are already on a stop path. They join the waves for ordering and timeout purposes, but do not receive another SIGTERM.
  • Starting services are not eligible. peinit cancels the startup, SIGKILLs the service cgroup if one exists, and transitions them to Failed with cause ShutdownWave while post-kill verification is pending. A cgroup still populated after the post-kill timeout takes the service to Abandoned with cause ProcessUnkillable and the cgroup is leaked. A Starting service whose job never forked skips the check and goes straight to Failed.
  • Inactive, Failed, Skipped, Backoff and Abandoned do not participate. Abandoned cgroups stay leaked and shutdown continues.

12.2.4 Step 4: Stop in reverse dependency order #

peinit builds the reverse dependency graph over hard dependencies and stops in waves:

  1. Each eligible service receives SIGTERM. Already-stopping ones do not.
  2. Each has StopTimeout to exit.
  3. On expiry, SIGKILL to the service's entire cgroup.
  4. No service is stopped until everything depending on it has stopped.

A service that sent STOPPING=1 does not receive a SIGTERM at all: it has already said it is shutting down, and peinit goes straight to the stop deadline.

12.2.4.1 Timing an already-stopping service #

peinit does not reset an already-Stopping service's clock, either when shutdown begins or when its wave becomes eligible. It uses the timing evidence retained from the stop path that put the service in Stopping:

  • If a Stop operation, or a Restart executing its stop leg, is in flight, that operation's retained timing governs.
  • Otherwise peinit uses service-level evidence, which carries the cause that initiated the transition — ExplicitStop, ShutdownWave, ConflictEviction or BindsToPropagation.

peinit requires the evidence to be present, to belong to a service actually in Stopping, to carry a cause matching the service's current cause, to name one of those four causes, and not to describe a deadline earlier than its own start. Evidence that is missing, stale or ambiguous fails closed rather than being guessed at — and it fails the whole shutdown, not just that participant, so a shutdown command with one such service is refused, and one discovered on a later wave ends the runtime loop.

An operation whose lifetime expires while it is still Pending — a later-wave stop waiting for its dependencies — fails that operation and its waiters. It does not authorise signalling the service before its wave is eligible. Shutdown owns the signalling; the operation object is an observation of it.

12.2.5 Step 5: Global timeout #

KeyDefaultMeaning
Machine\System\Boot\ShutdownTimeout90Seconds for the whole sequence.
Machine\System\Boot\PostKillTimeout5Seconds for a cgroup to drain after SIGKILL.

On expiry, every remaining participant's cgroup is killed, anything that does not drain within the post-kill timeout is marked Abandoned with its cgroup leaked, and shutdown continues regardless.

12.2.6 Step 6: Save the random seed #

After every service has stopped and before any unmount, peinit writes a fresh seed to /var/state/peinit/random-seed for the next boot: 512 bytes from the kernel CSPRNG on this machine, never copied from an image, protected so that only SYSTEM-equivalent authority can read or replace it.

The write is crash-conscious: a temporary file on the same filesystem, written, flushed, atomically renamed over the old seed, and the containing directory flushed. A failure is recorded and shutdown continues.

The forced and Critical-reboot paths skip it, along with the unmount step, and go directly to sync and the final action.

12.2.7 Step 7: Unmount #

  1. Snapshot the mount table first, from /proc/self/mountinfo.
  2. Attempt to unmount every remaining non-root mount in the namespace — not only what peinit mounted, so the Phase 1 set is covered by construction.
  3. Process in descending path depth, so children go before parents.
  4. A mount point already gone is a successful no-op.
  5. On failure, attempt a read-only remount. If that fails too, record it and continue.
  6. The root is never unmounted, but is remounted read-only at the end. A failure there is recorded and does not stop step 8.

12.2.8 Step 8: Sync and the final action #

This step is irreversible. Cleanup failures retained from steps 6 and 7 affect diagnostics only and never block it.

  1. sync(). Called on all three paths — graceful, forced and Critical reboot.
  2. reboot(2) with RB_POWER_OFF, RB_AUTOBOOT or RB_HALT_SYSTEM.
  3. If reboot(2) returns, the final action failed. peinit enters a minimal failed-shutdown state, keeps PID 1 alive, records the failure, and retries the same action no more than once a second. It does not restart services and does not enter recovery mode — finalisation has begun and there is nothing to go back to.

12.2.9 Shutdown during boot #

A shutdown requested while Phase 2 is still running takes effect immediately, through the same classification: Starting services are SIGKILLed, services that reached Active are stopped gracefully, and the boot is abandoned.

Edit this page