diff --git a/doc/ChangeLog.md b/doc/ChangeLog.md index e7ae2f06..fb3c4fe6 100644 --- a/doc/ChangeLog.md +++ b/doc/ChangeLog.md @@ -8,6 +8,12 @@ All relevant changes are documented in this file. ### Changes +- New `provides` setting for run/task/service/sysv blocks, naming + conditions the service asserts in addition to its own `pid/`. + Lets variants of one service, qualified with `if`, share the barrier + condition downstream services wait for, which a block title alone + could not express. Any namespace is allowed, and a second claim on + the same condition is refused with a warning naming the owner - The `command` setting in a block takes a list of candidates for the same service, `command = { "/lib/systemd/systemd-udevd", "-udevd" }`, and Finit starts the first one it finds. The line-based format could diff --git a/doc/config/migration.md b/doc/config/migration.md index 57060793..8a949876 100644 --- a/doc/config/migration.md +++ b/doc/config/migration.md @@ -117,27 +117,46 @@ daemon that has to wait for whichever hotplug daemon the system has: service if:mdev nowarn env:-/etc/default/sysklogd \ [S0123456789] syslogd -F $SYSLOGD_ARGS -- System log daemon -All of these are one service, `syslogd`, providing one `pid/syslogd` -barrier for everything downstream, so they cannot be given separate -titles without renaming that barrier. There are two ways to keep the -identity: +All of these are one service, `syslogd`, and everything downstream +waits for the one `pid/syslogd` barrier it provides. That barrier is +the reason the repetition existed: the title alone spells it, so +separate titles would rename it. - * put each variant in its own .conf file, since the ban on duplicate - titles is per file, or - * leave this one file in the line-based format, which Finit still - reads. Format is detected per file, so the rest of the system can - be block format. +Give each variant its own title and name the shared barrier with +`provides`: -A single variant converts the way anything else does: - - service syslogd { + service syslogd:udev { description = "System log daemon" runlevel = "S0123456789" if = "udevd" conditions = { "run/udevadm:5/success" } + provides = "pid/syslogd" envfile = "-/etc/default/sysklogd" command = "-syslogd -F $SYSLOGD_ARGS" } + service syslogd:mdev { + description = "System log daemon" + runlevel = "S0123456789" + if = "mdev" + conditions = { "run/coldplug/success" } + provides = "pid/syslogd" + envfile = "-/etc/default/sysklogd" + command = "-syslogd -F $SYSLOGD_ARGS" + } + +Whichever variant `if` qualifies asserts `pid/syslogd` on top of its +own `pid/syslogd:udev`, so downstream blocks need no change. The `if` +statements are meant to be mutually exclusive; if two of them do +qualify, the second claim is refused with a warning and only the first +variant supplies the barrier. See [Provided +Conditions](service-opts.md#provided-conditions). + +`initctl` now knows the variants apart, `initctl status syslogd:udev`, +and a bare `initctl status syslogd` still lists them all. + +Splitting the variants across files also works, since the ban on +duplicate titles is per file, as does leaving that one file in the +line-based format. Neither is needed for this shape any more. Cgroups ------- diff --git a/doc/config/service-opts.md b/doc/config/service-opts.md index af97384e..7b0fa509 100644 --- a/doc/config/service-opts.md +++ b/doc/config/service-opts.md @@ -88,6 +88,54 @@ the getty to run: "/sbin/getty -L 115200 /dev/ttyAMA0 vt100" } } +Provided Conditions +------------------- + +A service always asserts `pid/` for itself, named after the +block title. `provides` names conditions it asserts in addition to +that one: + + service syslogd:udev { + if = "udevd" + provides = "pid/syslogd" + command = "syslogd -F" + } + +This is what lets variants of one service, picked apart by +[`if`](services.md#conditional-execution), share the barrier that +everything downstream waits for. Each variant has its own title, so +each is its own service to `initctl`, while the condition they publish +stays the same. + +Any namespace works, `pid/`, `usr/`, `service/`, since the point is +publishing a name existing configuration already waits on. A value +without a namespace separator is not a condition and is rejected. The +list holds at most four. + +A provided condition is asserted and cleared with the service, exactly +like its own, so stopping the provider clears the barrier. + +Two services cannot supply the same condition. The second claim is +refused, with the owner named: + + finit.conf: second: provides condition already registered by service first, ignoring + +The service itself still registers and runs, only the claim is +dropped. Which one is "first" is .conf load order, so it follows the +file names, see [Files & Layout](files.md). + +A real identity outranks a claim on it. `provides = "pid/sshd"` in a +system that also runs a service titled `sshd` loses to that service, +because `pid/` is how Finit tracks the service itself. + +`initctl cond dump` names the owner of every condition, which for a +provided one is the service that claimed it: + + $ initctl cond dump + PID IDENT STATUS CONDITION + 1234 syslogd:udev on + 1234 syslogd:udev on + Duplicate Titles ---------------- diff --git a/doc/config/services.md b/doc/config/services.md index 1e242f0e..4f1a18b3 100644 --- a/doc/config/services.md +++ b/doc/config/services.md @@ -348,3 +348,9 @@ can be written as: conditions = { "pid/sysrepo" } command = "confd ..." } + +Variants of one service are often qualified this way, one per platform, +and they usually have to supply the same barrier to whatever waits for +them. Each variant needs its own title, since a title is an identity, +and the shared barrier is named with `provides`. See [Provided +Conditions](service-opts.md#provided-conditions). diff --git a/system/10-hotplug.conf.in b/system/10-hotplug.conf.in index f0e8c86c..bf38c37a 100644 --- a/system/10-hotplug.conf.in +++ b/system/10-hotplug.conf.in @@ -21,9 +21,21 @@ # The mdev and mdevd systems wait for a different coldplug condition, so they # need their own block, and a block title is a service identity: two blocks # titled syslogd in one file are two declarations of one service, which Finit -# rejects. Give each variant its own file, or keep them as one-liners in the -# line-based format, which has no titles and allows the repetition. See -# doc/config/migration.md for both. +# rejects. Give each variant its own title and name the shared barrier that +# everything downstream waits for: +# +# service syslogd:udev { +# if = "udevd" +# conditions = { "run/udevadm:5/success" } +# provides = "pid/syslogd" +# command = "syslogd -F" +# } +# service syslogd:mdev { +# if = "mdev" +# conditions = { "run/coldplug/success" } +# provides = "pid/syslogd" +# command = "syslogd -F" +# } # # Override this file by copying it to /etc/finit.d/, using the same name, then # change the contents any way you like, it can even be empty.