2.5 Phase 2

With registryd serving, peinit reads the service graph and boots the system from it. Phase 2 is entirely registry-driven.

2.5.1 Reading the definitions #

peinit reads every key under Machine\System\Services\. The reads are bounded by LCS's request timeout: if registryd hangs mid-read, peinit receives ETIMEDOUT and enters recovery.

Decoding is per key. A definition that fails to decode — an invalid service name, a malformed trigger, an unclosed quote in a command, a registry: check naming an uncacheable key, a duplicate known field, an unrecognised value for an enumerated dword — fails that service, which is marked Failed with cause ValidationError. The boot proceeds with every other definition, and anything that depended on the failed service fails in turn through the ordinary dependency propagation.

Only services carrying a boot trigger are root candidates. A service with no triggers is demand-only and is not a root, though it can still be pulled into the boot transaction as somebody's dependency. A service with Disabled=1 is excluded from the boot graph entirely, but its definition is still loaded into the in-memory model so it can be started by hand later.

2.5.2 Building and validating the graph #

The boot graph is every boot-triggered root candidate plus the transitive closure of their Requires, BindsTo, and existing non-disabled Wants dependencies. Requires and BindsTo pull their target in even if the target has no boot trigger. Wants targets come in as best-effort members; missing or disabled ones are ignored. A missing or disabled Requires or BindsTo target blocks the dependent with cause DependencyFailure, and that blocking propagates.

peinit topologically sorts the graph and validates it before starting anything. The rules are in §7.2; the outcomes that matter here are:

  • A cycle fails every service in it. A cycle involving a Critical service downgrades the boot to Safe mode without rebooting.
  • An unresolvable conflict fails both services. Same downgrade if either is Critical.
  • A missing Requires target fails the dependent.
  • Warnings — a Readiness=Alive service with dependents that require it — are logged and do not prevent boot.

2.5.3 Starting #

peinit walks the graph and starts services, parallelising wherever the graph allows, up to a configurable limit:

KeyDefaultMeaning
Machine\System\Boot\MaxParallelStarts10Services starting concurrently.

An absent key uses the default. A value of zero, a type mismatch, or a malformed payload is invalid boot configuration and sends peinit to recovery — running the scheduler with an effective limit of zero would hang the boot rather than fail it.

As each service reaches a dependent-satisfying state — Active for Simple, Completed for Oneshot with or without RemainAfterExit, Skipped for a service whose conditions did not hold — its dependents become eligible and join the start queue. A Oneshot without RemainAfterExit passes through Completed, releasing its dependents, and then goes Inactive.

Dependents blocked on a Requires or BindsTo target wait for that target to reach a satisfying state. Dependents blocked on a Wants target wait only for it to reach any terminal state, satisfying or not — which is what makes Wants ordering rather than dependency.

2.5.3.1 The typical order #

Nothing below is hardcoded. It falls out of the dependency graph that the standard role definitions produce, and an administrator who changes a dependency gets a different order.

  1. eudev — device management. SYSTEM, with RequiredPrivileges stripped to the minimum it needs. Starts before authd exists.
  2. lpsd — the local identity database. Depends only on registryd.
  3. authd — the identity authority. Depends on registryd and lpsd. Once it is ready, token minting is available.
  4. eventd — logging and audit. Services started before it log into peinit's pre-eventd buffer.
  5. Networking — the first service to receive a token from authd.
  6. Application services, in dependency order.
  7. Login services, last, so the system is operational before it accepts a session.

2.5.3.2 The bootstrap matrix #

ServicePhaseIdentityToken fromReadinessErrorControl
registryd1SYSTEMminted by peinitNotifyCritical
eudev2SYSTEMminted by peinit, privileges strippedAliveNormal
lpsd2SYSTEMminted by peinitNotifyCritical
authd2SYSTEMminted by peinitNotifyCritical
eventd2SYSTEMminted by peinitNotifyCritical
networking2service tokenauthdNotifyNormal
sshd2service tokenauthdAliveNormal
application services2service tokenauthdper-serviceNormal

2.5.4 Deferred starts #

A service whose trigger is boot:settled is not part of the boot plan at all. It is not a root, it does not consume the parallel-start budget, it is not counted towards boot success, and it cannot block or delay anything. peinit starts it after the plan, once the boot has stopped moving.

"Stopped moving" is precise: every service in the plan — those that were started and those that were blocked — is in a state it will not leave without help. Active, Completed, Failed, Skipped, Abandoned and Inactive all count as settled. Starting, Reloading, Stopping and Backoff do not, because a service between restart attempts is going to produce more output.

A deadline bounds the wait:

KeyDefaultMeaning
Machine\System\Boot\SettleTimeout5Seconds before deferred services start regardless.

The deadline is measured from the moment the plan was observed. An absent key uses the default; a type mismatch or a bad length sends peinit to recovery. Zero is legal and means "start on the next turn, settled or not".

Whichever comes first — the set settling or the deadline expiring — the deferred services start, once, each independently. A start that fails is recorded and dropped: one refusing service does not stop the others and does not affect the boot. The dispatch carries a flag saying whether the deadline expired rather than the set settling, so a service that cares whether the boot was still moving can be told.

2.5.5 Boot success #

A boot is successful once every Critical service has held a dependent-satisfying state continuously for a grace period:

KeyDefaultMeaning
Machine\System\Boot\BootSuccessGrace30Seconds of held health before the boot counts.

The criterion is satisfying, not Active. A Critical Oneshot reaches Completed and never reaches Active, so a test for Active would make such a service unable to ever mark a boot successful. Skipped counts too.

Success resets the boot attempt counter to zero (§2.7).

2.5.6 Failure summary #

FailureResponse
A service definition fails to decodeRecovery
A registry read times outRecovery
Invalid MaxParallelStarts or SettleTimeoutRecovery
A dependency cycleAll services in it Failed; Safe mode if any is Critical (see below)
An unresolvable conflictBoth Failed; Safe mode if either is Critical (see below)
A missing Requires targetThe dependent Failed
A Critical service fails during bootRestart budget, then reboot
A non-Critical service failsFailed; its Requires dependents fail; the rest continue
authd unavailable when a service needs a tokenThat service Failed

The two Safe-mode rows carry a caveat. When the downgrade fires, peinit rebuilds the graph in Safe mode and discards the Full-mode one, so the services that caused it are not marked Failed — they are never entered into the blocked set at all. What records them is the boot-level downgrade finding described in Boot modes.

Edit this page