3.1 Services
A service is the primary unit of management: a definition in the
registry, a runtime state, a Security Descriptor, and at most one
running main process. Definitions live under
Machine\System\Services\<name>, where the key name is the service
name. peinit reads them at Phase 2 boot and on an explicit
reload-config.
3.1.1 Names #
A service name is 1 to 128 bytes drawn from [A-Za-z0-9._-]. Any other
byte makes the name invalid.
Two exclusions are deliberate. / is out because names map directly
onto cgroup identifiers (§5.1) and onto registry key names, and a name
containing a separator would mean something different in each. : is
reserved for peinit's own synthetic naming.
3.1.2 The two types #
3.1.2.1 Simple #
A long-running daemon. peinit forks, installs a token, and execs the binary; the process is the service. When it exits, the service has stopped. This is the default and covers nearly everything — registryd, authd, sshd, application services.
Readiness comes from the Readiness field. Notify, the default,
waits for READY=1. Alive treats the process as ready the moment it
exists.
The service goes Active on readiness and stays Active until the process exits or something stops it.
3.1.2.2 Oneshot #
A run-to-completion task: database initialisation, a schema migration, a directory that has to exist. peinit forks, installs a token, execs, and waits for the exit.
Readiness is ignored. A Oneshot's readiness is always "it exited
successfully", because READY=1 is meaningless from a process whose job
is to finish. Success means exit code 0, or any code listed in
SuccessExitCodes.
The differences from Simple are:
- A successful exit goes to Completed. With
RemainAfterExit=1it stays there; without, it passes through Completed to release dependents and then goes Inactive. - A non-zero exit goes to Failed.
ExecStartPostruns after the successful exit rather than after a readiness signal, and does not run at all if the Oneshot failed.StartTimeoutcovers the entire execution, from the first pre-hook to the process exiting.
RemainAfterExit matters when the Completed state itself is the useful
information — so a status query shows a migration as finished rather
than as inactive.
3.1.3 Forking daemons #
peinit does not support them. A service that double-forks to daemonise
itself is working around a problem that does not exist when the service
manager tracks the process it spawned, and peinit tracks its child
through a pidfd obtained at fork. There is no MAINPID=, and no way to
point supervision at a different process.
A legacy binary that insists on double-forking is wrapped by whoever
packages it — a script with a --no-daemon flag, typically. That is a
packaging concern.