systemd / systemd/systemd

Propagate After= from target to its dependencies

Open
#3,750 10 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

pid1 RFE 🎁
Dominant language
C
Stars
16.7k
Forks
4.7k
Avg merge
1d 6h
Merged PRs (30d)
140

Description

Submission type
  • Bug report
  • Request for enhancement (RFE)
systemd version the issue has been seen with

230, master

This came up while discussing and implementing graphical sessions with systemd. There are a few "set up" services like gpg-agent (poking environment variables into D-Bus) or session-migration (updating obsolete gsettings keys after upgrade and the like) which need to run before the desktop and applications start. It is currently very hard to order a bunch of services after a bunch of "early" services with targets. This can be demonstrated with some user units:

$ cat early.target 
[Unit]
Description=early services
Requires=setup.service

$ cat setup.service 
[Unit]
Description=setup for late services

[Service]
Type=oneshot
ExecStart=/bin/sleep 2

$ cat late.target 
[Unit]
Description=late services
Requires=early.target
Wants=some.service

$ cat some.service 
[Unit]
Description=some service

[Service]
ExecStart=/bin/sleep infinity

So the intention is that early.target and its dependencies run first, then late.target and its dependencies. But starting late.target immediately starts some.service as there is nothing that would delay that service. Only the late.target itself waits for early.target (but that is not the point here):

Jul 19 09:14:22 donald systemd[3856]: Started some service.
Jul 19 09:14:22 donald systemd[3856]: Starting setup for late services...
Jul 19 09:14:24 donald systemd[3856]: Started setup for late services.
Jul 19 09:14:24 donald systemd[3856]: Reached target early services.
Jul 19 09:14:24 donald systemd[3856]: Reached target late services.

With current systemd one would instead have to put the After=early.target into every single *.service, of which there are a lot.

On the system side the main divide that we have is sysinit.target and the DefaultDependencies= mechanism helps to implicitly add Requires/After=sysinit.target to every unit in multi-user. It would be nice to have a generalization of that, in the spirit of late.target saying [Target]\nPropagateDependencies=yes (this is not a great property name, I know) so that all of its dependencies inherit the same After= and Before= as the target itself (maybe also Requires= and Wants=, for consistency/symmetry).

This would help to more elegantly model the use case above, and we could perhaps also use that to replace the in-code implementation of DefaultDependencies=yes with adding this flag to multi-user.target.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the example units early.target, setup.service, late.target, and some.service, and compare the requested ordering with current behavior. A complete change would establish the proposed propagation semantics, including which dependency and ordering relationships are covered; the issue names no source files or tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux
Domain
operating-systems
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.