Fixes several correctness bugs primarily around modular services' recent
reload/notification options (#535695) and adds compliance coverage to guard them.
Fixes:
- `lib/services/service.nix`:
- the reload-conflict assertion had inverted polarity, so it fired on the
default configuration
- the `mkIf` guard on `process.reloadCommand` had a misplaced paren, applying
`!= null` to the `mkIf` result rather than to the condition
- `process.reloadSignal` derives `process.reloadCommand`, so the assertion
could not check `reloadCommand != null` -- that fired on every signal-only
service. The command is now derived at `mkDefault` priority and the
assertion is gated on `options.process.reloadCommand.highestPrio`, firing
only when the user also set `reloadCommand` explicitly.
- change `notificationProtocol` to a sub-module type
- `nixos/modules/system/service/systemd/service.nix`:
- `systemd.mainExecReload`'s default ran `escapeSystemdExecArgs` (a list
escaper) on the `nullOr str` `process.reloadCommand`; this threw
`expected a list but found a string` and would have mangled `$MAINPID`. It
now uses `process.reloadCommand` verbatim.
- the `Type` default read a non-existent
`config.serviceManager.notificationProtocol` instead of
`config.notificationProtocol`.
Tests:
Extend the modular-service compliance suite to guard the above:
- Portable (manager-agnostic) eval assertions: `reloadSignal` derives
`reloadCommand`, the conflict assertion does not fire on signal-only services
but does when both are set explicitly, and `notificationProtocol.systemd`/`.s6`
default to `false`.
- systemd-specific eval assertions: `serviceConfig.Type` (simple/notify) and
`serviceConfig.ExecReload` are asserted on the resolved host units. This
directly guards the `mainExecReload` fix, which threw before it.
- Runtime reload compliance test: a nested reloadable sub-service is started and
reloaded, asserting the service observed the reload (recorded a SIGHUP marker).
`callReload` receives the service's name path (the list of names from the
top-level service down to the target sub-service); each integration joins it
per its own unit-naming convention (NixOS dash-joins to the systemd unit name,
e.g. `reload-inner.service`). Keeping it a path list rather than a read-only
submodule option keeps the suite manager-agnostic.
- `doc/build-helpers/testers.chapter.md`: document `callReload`.
Follow-up to #535695.
Signed-off-by: cinereal <cinereal@riseup.net>
Assisted-by: Claude:claude-opus-4-8
Every in-tree union/intersection use has exactly two members, and the
binary form verifies without allocating a closure or calling the any/all
primop per check. check-meta.nix switches to either/both; union and
intersection are kept for potential future use.
Assisted-by: Claude Code (Claude Fable 5)
throwIfNot sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
throwIfNot sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
throwIfNot sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
throwIfNot sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
throwIf sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
throwIf sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
throwIf sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
assertMsg sends our error message through a function call, even if the
error condition doesn't trigger. This requires a lot of thunk allocation
that can be easily avoided.
Nix 2.28 was the last release packaged with the monolithic
common-meson.nix expression and is no longer maintained upstream.
Drop it together with the now-unused common-meson.nix and nix-perl.nix
helpers and the storeDir/stateDir/confDir plumbing that only fed
that code path.