Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Systemd socket activation #1

Open
2 tasks
untzag opened this issue May 19, 2022 · 0 comments
Open
2 tasks

Systemd socket activation #1

untzag opened this issue May 19, 2022 · 0 comments

Comments

@untzag
Copy link
Member

untzag commented May 19, 2022

Narrower scope issue stemming from yaqd-core-python#19

Systemd allows for activating daemons on incomming socket communications:

From man 7 daemon:

Socket-Based Activation

   In order to maximize the possible parallelization and robustness and simplify configuration and
   development, it is recommended for all new-style daemons that communicate via listening sockets
   to employ socket-based activation. In a socket-based activation scheme, the creation and
   binding of the listening socket as primary communication channel of daemons to local (and
   sometimes remote) clients is moved out of the daemon code and into the init system. Based on
   per-daemon configuration, the init system installs the sockets and then hands them off to the
   spawned process as soon as the respective daemon is to be started. Optionally, activation of
   the service can be delayed until the first inbound traffic arrives at the socket to implement
   on-demand activation of daemons. However, the primary advantage of this scheme is that all
   providers and all consumers of the sockets can be started in parallel as soon as all sockets
   are established. In addition to that, daemons can be restarted with losing only a minimal
   number of client transactions, or even any client request at all (the latter is particularly
   true for state-less protocols, such as DNS or syslog), because the socket stays bound and
   accessible during the restart, and all requests are queued while the daemon cannot process
   them.

New-style daemons which support socket activation must be able to receive their sockets from
the init system instead of creating and binding them themselves. For details about the
programming interfaces for this scheme provided by systemd, see sd_listen_fds(3) and sd-
daemon(3). For details about porting existing daemons to socket-based activation, see below.
With minimal effort, it is possible to implement socket-based activation in addition to
traditional internal socket creation in the same codebase in order to support both new-style
and old-style init systems from the same daemon binary.

systemd implements socket-based activation via .socket units, which are described in
systemd.socket(5). When configuring socket units for socket-based activation, it is essential
that all listening sockets are pulled in by the special target unit sockets.target. It is
recommended to place a WantedBy=sockets.target directive in the "[Install]" section to
automatically add such a dependency on installation of a socket unit. Unless
DefaultDependencies=no is set, the necessary ordering dependencies are implicitly created for
all socket units. For more information about sockets.target, see systemd.special(7). It is not
necessary or recommended to place any additional dependencies on socket units (for example from
multi-user.target or suchlike) when one is installed in sockets.target.

Doing this involves a few steps:

  • Actually implement accepting the already open socket from the system layer (with fallback to opening ourselves when not run on systemd)
  • Write socket unit files and link them together appropriately

https://docs.python.org/3/library/socket.html?highlight=socket#socket.fromfd

I believe this is how it is handed off using the environment variable $LISTEN_FDS_START
Which will provid FDs 3, 4, 5, ... for the sockets specified.

Since we may have multiple sockets in one process, we do in fact need to be concerned about the number, and probably should use names to check, especially as we allow disabling of individual ones via the config...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant