[systemd-devel] Changes to dependency graph during boot
Lennart Poettering
lennart at poettering.net
Tue Jun 25 09:14:08 UTC 2019
On Mo, 24.06.19 16:41, Conrad Hoffmann (ch at bitfehler.net) wrote:
> Hi,
>
> TL;DR: I was wondering what happens if a unit executed early during the
> boot process changes the current dependency graph by either enabling or
> even starting another unit that was previously disabled. Is this defined
> behaviour, and if so what are the rules?
So, this is usually safe, but there are some issues with this, and I
would not recommend reloading the dep tree during a regular, clean
boot. It's not designed for that.
In some cases reloading the unit files during operation is not
safe. Specifically, consider a unit file with contains something like
that:
```
[Sevice]
Type=oneshot
ExecStart=/usr/bin/something with-a-param
ExecStart=/usr/bin/something-else also-a-parm
ExecStart=/usr/bin/something-third third-param
```
Now your service is already at the execution of the middle program,
and now you reload the whole thing and make a modification of the unit
file:
```
[Sevice]
Type=oneshot
ExecStart=/usr/bin/something with-a-param
ExecStart=/usr/bin/something-else changed-param
ExecStart=/usr/bin/something-third third-param
```
Now the question is where execution should continue: the middle line
was changed, and we can easily see that as humans, but it's not clear
from systemd's pov. It could also be that the old line was removed and
a new line inserted instead. Depending how you see that after the
reload it could mean to easier continue execution with the second line
or with the third line, and it's really not clear semantically what is
meant here.
systemd employs some heuristics and tries to do some reasonable smart
choice, but it's black magic and it might be wrong. But this means:
reloading the whole daemon during clean code paths is
questionnable. it's fine doing that when you install or remove
packages, i.e. not in common codepaths but only in an upgrade
codepaths, but doing that on every single boot, as part of a clean
start-up is something i would advocate like that.
Hence: changing units and issuing daemon reloads during boot-up is
ugly. Don't do it. Besides these issues pointed out above, it's also
slow.
Noe that if you have all units in place already and just want to
enqueue them, that's entirely safe, the common case and
recommended. The suggestions above are just about of modifying units,
creating them, removing them and then reloading systemd. Don't do that.
In systemd, we have the "generator" concept, that is our recommended
way to extend the unit dependency tree with foreign and automatically
generated units. Generators run very early during boot, before the
initial transaction is generated, which means everything they do is
already complete by the time systemd calculates the initial
transaction, and thus while that transaction and all its jobs are
executed unit files are not changed anymore. Generally I'd strongly
recommend using generators over manually modifying/creating units
during boot combined with a daemon reload.
For more information about generators see:
https://www.freedesktop.org/software/systemd/man/systemd.generator.html
Lennart
--
Lennart Poettering, Berlin
More information about the systemd-devel
mailing list