Merge pull request #29186 from keszybz/man-notifications-and-fd-store

man: notifications and fd store
This commit is contained in:
Luca Boccassi 2023-09-19 00:36:24 +01:00 committed by GitHub
commit c2077ae0c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 290 additions and 275 deletions

View file

@ -146,13 +146,11 @@
new-style daemons. This makes it easier to supervise and control
them at runtime and simplifies their implementation.</para>
<para>For developing a new-style daemon, none of the
initialization steps recommended for SysV daemons need to be
implemented. New-style init systems such as systemd make all of
them redundant. Moreover, since some of these steps interfere
with process monitoring, file descriptor passing and other
functionality of the init system, it is recommended not to
execute them when run as new-style service.</para>
<para>For developing a new-style daemon, none of the initialization steps recommended for SysV daemons
need to be implemented. New-style init systems such as systemd make all of them redundant. Moreover,
since some of these steps interfere with process monitoring, file descriptor passing, and other
functionality of the service manager, it is recommended not to execute them when run as new-style
service.</para>
<para>Note that new-style init systems guarantee execution of daemon processes in a clean process context: it is
guaranteed that the environment block is sanitized, that the signal handlers and mask is reset and that no
@ -166,20 +164,28 @@
following:</para>
<orderedlist>
<listitem><para>If <constant>SIGTERM</constant> is received,
shut down the daemon and exit cleanly.</para></listitem>
<listitem><para>If applicable, the daemon should notify the service manager about startup completion
or status updates via the
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
interface, in particular <varname>READY=1</varname> and <varname>STATUS=…</varname>.
</para></listitem>
<listitem><para>If <constant>SIGHUP</constant> is received,
reload the configuration files, if this
applies.</para></listitem>
<listitem><para>If <constant>SIGTERM</constant> is received, shut down the daemon and exit cleanly.
A <varname>STOPPING=1</varname> notification should be sent via
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
<listitem><para>Provide a correct exit code from the main
daemon process, as this is used by the init system to detect
service errors and problems. It is recommended to follow the
exit code scheme as defined in the <ulink
<listitem><para>If <constant>SIGHUP</constant> is received, reload the configuration files, if this
applies. This should be combined with notifications via
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>:
<varname>RELOADING=1</varname> and <varname>READY=1</varname>.
</para></listitem>
<listitem><para>Provide a correct exit code from the main daemon process, as this is used by the
service manager to detect service errors and problems. It is recommended to follow the exit code
scheme as defined in the <ulink
url="http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html">LSB
recommendations for SysV init
scripts</ulink>.</para></listitem>
recommendations for SysV init scripts</ulink>.</para></listitem>
<listitem><para>If possible and applicable, expose the
daemon's control interface via the D-Bus IPC system and grab a
@ -192,15 +198,12 @@
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details.</para></listitem>
<listitem><para>As much as possible, rely on the init system's
functionality to limit the access of the daemon to files,
services and other resources, i.e. in the case of systemd,
rely on systemd's resource limit control instead of
implementing your own, rely on systemd's privilege dropping
code instead of implementing it in the daemon, and similar.
See
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for the available controls.</para></listitem>
<listitem><para>As much as possible, rely on the service manager's functionality to limit the access
of the daemon to files, services, and other resources, i.e. in the case of systemd, rely on systemd's
resource limit control instead of implementing your own, rely on systemd's privilege dropping code
instead of implementing it in the daemon, and so on. See
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
the available controls.</para></listitem>
<listitem><para>If D-Bus is used, make your daemon
bus-activatable by supplying a D-Bus service activation
@ -222,29 +225,25 @@
can be restarted without losing a single request. See below
for details.</para></listitem>
<listitem><para>If applicable, a daemon should notify the init
system about startup completion or status updates via the
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
interface.</para></listitem>
<listitem><para>If the service opens sockets or other files on it own, and those file descriptors
shall survive a restart, the daemon should store them in the service manager via
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> with
<varname>FDSTORE=1</varname>..</para></listitem>
<listitem><para>Instead of using the
<function>syslog()</function> call to log directly to the
system syslog service, a new-style daemon may choose to simply
log to standard error via <function>fprintf()</function>,
which is then forwarded to syslog by the init system. If log
levels are necessary, these can be encoded by prefixing
individual log lines with strings like
<literal>&lt;4&gt;</literal> (for log level 4 "WARNING" in the
syslog priority scheme), following a similar style as the
Linux kernel's <function>printk()</function> level system. For
details, see
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
<listitem><para>Instead of using the <function>syslog()</function> call to log directly to the system
syslog service, a new-style daemon may choose to simply log to standard error via
<function>fprintf()</function>, which is then forwarded to syslog. If log levels are necessary, these
can be encoded by prefixing individual log lines with strings like <literal>&lt;4&gt;</literal> (for
log level 4 "WARNING" in the syslog priority scheme), following a similar style as the Linux kernel's
<function>printk()</function> level system. For details, see
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para></listitem>
<listitem><para>As new-style daemons are invoked without a controlling TTY (but as their own session
leaders) care should be taken to always specify `O_NOCTTY` on `open()` calls that possibly reference
a TTY device node, so that no controlling TTY is accidentally acquired.</para></listitem>
leaders) care should be taken to always specify <constant>O_NOCTTY</constant> on
<citerefentry><refentrytitle>open</refentrytitle><manvolnum>2</manvolnum></citerefentry>
calls that possibly reference a TTY device node, so that no controlling TTY is accidentally
acquired.</para></listitem>
</orderedlist>
@ -282,17 +281,14 @@
<refsect2>
<title>Activation on Boot</title>
<para>Old-style daemons are usually activated exclusively on
boot (and manually by the administrator) via SysV init scripts,
as detailed in the <ulink
<para>Old-style daemons are usually activated exclusively on boot (and manually by the administrator)
via SysV init scripts, as detailed in the <ulink
url="http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html">LSB
Linux Standard Base Core Specification</ulink>. This method of
activation is supported ubiquitously on Linux init systems, both
old-style and new-style systems. Among other issues, SysV init
scripts have the disadvantage of involving shell scripts in the
boot process. New-style init systems generally employ updated
versions of activation, both during boot-up and during runtime
and using more minimal service description files.</para>
Linux Standard Base Core Specification</ulink>. This method of activation is supported ubiquitously on
Linux init systems, both old-style and new-style systems. Among other issues, SysV init scripts have
the disadvantage of involving shell scripts in the boot process. New-style init systems generally use
updated versions of activation, both during boot-up and during runtime and using more minimal service
description files.</para>
<para>In systemd, if the developer or administrator wants to
make sure that a service or other unit is activated
@ -312,42 +308,29 @@
<refsect2>
<title>Socket-Based Activation</title>
<para>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.</para>
<para>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 use
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 service manager. Based on per-daemon configuration, the service manager
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.</para>
<para>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
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
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.</para>
<para>New-style daemons which support socket activation must be able to receive their sockets from the
service manager instead of creating and binding them themselves. For details about the programming
interfaces for this scheme provided by systemd, see
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry> and
<citerefentry><refentrytitle>sd-daemon</refentrytitle><manvolnum>3</manvolnum></citerefentry>. 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.</para>
<para>systemd implements socket-based activation via
<filename>.socket</filename> units, which are described in
@ -373,23 +356,16 @@
<refsect2>
<title>Bus-Based Activation</title>
<para>When the D-Bus IPC system is used for communication with
clients, new-style daemons should employ bus activation so that
they are automatically activated when a client application
accesses their IPC interfaces. This is configured in D-Bus
service files (not to be confused with systemd service unit
files!). To ensure that D-Bus uses systemd to start-up and
maintain the daemon, use the <varname>SystemdService=</varname>
directive in these service files to configure the matching
systemd service for a D-Bus service. e.g.: For a D-Bus service
whose D-Bus activation file is named
<filename>org.freedesktop.RealtimeKit.service</filename>, make
sure to set
<varname>SystemdService=rtkit-daemon.service</varname> in that
file to bind it to the systemd service
<filename>rtkit-daemon.service</filename>. This is needed to
make sure that the daemon is started in a race-free fashion when
activated via multiple mechanisms simultaneously.</para>
<para>When the D-Bus IPC system is used for communication with clients, new-style daemons should use
bus activation so that they are automatically activated when a client application accesses their IPC
interfaces. This is configured in D-Bus service files (not to be confused with systemd service unit
files!). To ensure that D-Bus uses systemd to start-up and maintain the daemon, use the
<varname>SystemdService=</varname> directive in these service files to configure the matching systemd
service for a D-Bus service. e.g.: For a D-Bus service whose D-Bus activation file is named
<filename>org.freedesktop.RealtimeKit.service</filename>, make sure to set
<varname>SystemdService=rtkit-daemon.service</varname> in that file to bind it to the systemd service
<filename>rtkit-daemon.service</filename>. This is needed to make sure that the daemon is started in a
race-free fashion when activated via multiple mechanisms simultaneously.</para>
</refsect2>
<refsect2>
@ -449,10 +425,10 @@
<title>Other Forms of Activation</title>
<para>Other forms of activation have been suggested and implemented in some systems. However, there are
often simpler or better alternatives, or they can be put together of combinations of the schemes
above. Example: Sometimes, it appears useful to start daemons or <filename>.socket</filename> units
when a specific IP address is configured on a network interface, because network sockets shall be bound
to the address. However, an alternative to implement this is by utilizing the Linux
often simpler or better alternatives, or they can be put together of combinations of the schemes above.
Example: Sometimes, it appears useful to start daemons or <filename>.socket</filename> units when a
specific IP address is configured on a network interface, because network sockets shall be bound to the
address. However, an alternative to implement this is by utilizing the Linux
<constant>IP_FREEBIND</constant>/<constant>IPV6_FREEBIND</constant> socket option, as accessible via
<varname>FreeBind=yes</varname> in systemd socket files (see
<citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
@ -460,15 +436,14 @@
address, and hence allows bindings to a particular IP address before it actually becomes available,
making such an explicit dependency to the configured address redundant. Another often suggested trigger
for service activation is low system load. However, here too, a more convincing approach might be to
make proper use of features of the operating system, in particular, the CPU or I/O scheduler of
Linux. Instead of scheduling jobs from userspace based on monitoring the OS scheduler, it is advisable
to leave the scheduling of processes to the OS scheduler itself. systemd provides fine-grained access
to the CPU and I/O schedulers. If a process executed by the init system shall not negatively impact the
amount of CPU or I/O bandwidth available to other processes, it should be configured with
<varname>CPUSchedulingPolicy=idle</varname> and/or
<varname>IOSchedulingClass=idle</varname>. Optionally, this may be combined with timer-based activation
to schedule background jobs during runtime and with minimal impact on the system, and remove it from
the boot phase itself.</para>
make proper use of features of the operating system, in particular, the CPU or I/O scheduler of Linux.
Instead of scheduling jobs from userspace based on monitoring the OS scheduler, it is advisable to
leave the scheduling of processes to the OS scheduler itself. systemd provides fine-grained access to
the CPU and I/O schedulers. If a process executed by the service manager shall not negatively impact
the amount of CPU or I/O bandwidth available to other processes, it should be configured with
<varname>CPUSchedulingPolicy=idle</varname> and/or <varname>IOSchedulingClass=idle</varname>.
Optionally, this may be combined with timer-based activation to schedule background jobs during runtime
and with minimal impact on the system, and remove it from the boot phase itself.</para>
</refsect2>
</refsect1>
@ -675,26 +650,20 @@ fi</programlisting>
is useful not only for using the daemon in new-style init
systems, but also to ease debugging.</para></listitem>
<listitem><para>If the daemon offers interfaces to other
software running on the local system via local
<constant>AF_UNIX</constant> sockets, consider implementing
socket-based activation (see above). Usually, a minimal patch is
sufficient to implement this: Extend the socket creation in the
daemon code so that
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>
is checked for already passed sockets first. If sockets are
passed (i.e. when <function>sd_listen_fds()</function> returns a
positive value), skip the socket creation step and use the
passed sockets. Secondly, ensure that the file system socket
nodes for local <constant>AF_UNIX</constant> sockets used in the
socket-based activation are not removed when the daemon shuts
down, if sockets have been passed. Third, if the daemon normally
closes all remaining open file descriptors as part of its
initialization, the sockets passed from the init system must be
spared. Since new-style init systems guarantee that no left-over
file descriptors are passed to executed processes, it might be a
good choice to simply skip the closing of all remaining open
file descriptors if sockets are passed.</para></listitem>
<listitem><para>If the daemon offers interfaces to other software running on the local system via local
<constant>AF_UNIX</constant> sockets, consider implementing socket-based activation (see above).
Usually, a minimal patch is sufficient to implement this: Extend the socket creation in the daemon code
so that
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry> is
checked for already passed sockets first. If sockets are passed (i.e. when
<function>sd_listen_fds()</function> returns a positive value), skip the socket creation step and use
the passed sockets. Secondly, ensure that the file system socket nodes for local
<constant>AF_UNIX</constant> sockets used in the socket-based activation are not removed when the
daemon shuts down, if sockets have been passed. Third, if the daemon normally closes all remaining open
file descriptors as part of its initialization, the sockets passed from the service manager must be
spared. Since new-style init systems guarantee that no left-over file descriptors are passed to
executed processes, it might be a good choice to simply skip the closing of all remaining open file
descriptors if sockets are passed.</para></listitem>
<listitem><para>Write and install a systemd unit file for the
service (and the sockets if socket-based activation is used, as

View file

@ -78,23 +78,32 @@
<para>The following commands are understood:</para>
<variablelist>
<varlistentry>
<term><command>add <replaceable>KERNEL-VERSION</replaceable> <replaceable>KERNEL-IMAGE</replaceable> [<replaceable>INITRD-FILE</replaceable> ...]</command></term>
<term>
<command>add</command>
<replaceable>KERNEL-VERSION</replaceable>
<replaceable>KERNEL-IMAGE</replaceable> [<replaceable>INITRD-FILE</replaceable> ...]
</term>
<listitem>
<para>This command expects a kernel version string and a path to a kernel image file as arguments.
Optionally, one or more initrd images may be specified as well (note that plugins might generate
additional ones). <command>kernel-install</command> calls the executable files from
<filename>/usr/lib/kernel/install.d/*.install</filename> and
<filename>/etc/kernel/install.d/*.install</filename> (i.e. the plugins) with the following
arguments:</para>
additional ones).</para>
<programlisting>add <replaceable>KERNEL-VERSION</replaceable> <filename>$BOOT/<replaceable>ENTRY-TOKEN</replaceable>/<replaceable>KERNEL-VERSION</replaceable>/</filename> <replaceable>KERNEL-IMAGE</replaceable> [<replaceable>INITRD-FILE</replaceable> ...]</programlisting>
<para>The executable files from <filename>/usr/lib/kernel/install.d/*.install</filename> and
<filename>/etc/kernel/install.d/*.install</filename> (i.e. the plugins) are called with the
following arguments:</para>
<programlisting>add <replaceable>KERNEL-VERSION</replaceable> <filename>$BOOT/<replaceable>ENTRY-TOKEN</replaceable>/<replaceable>KERNEL-VERSION</replaceable>/</filename> <replaceable>KERNEL-IMAGE</replaceable> \
[<replaceable>INITRD-FILE</replaceable> ...]</programlisting>
<para>The third argument directly refers to the path where to place kernel images, initrd
images and other resources for <ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot
images and other resources for
<ulink url="https://uapi-group.org/specifications/specs/boot_loader_specification">Boot
Loader Specification</ulink> Type #1 entries (the "entry directory"). If other boot loader schemes
are used the parameter may be ignored. The <replaceable>ENTRY-TOKEN</replaceable> string is
typically the machine ID and is supposed to identify the local installation on the system. For
details see below.</para>
are used the parameter may be ignored.</para>
<para>The <replaceable>ENTRY-TOKEN</replaceable> string is typically the machine ID and is supposed
to identify the local installation on the system. For details see below.</para>
<para>Two default plugins execute the following operations in this case:</para>
@ -136,10 +145,11 @@
<varlistentry>
<term><command>remove <replaceable>KERNEL-VERSION</replaceable></command></term>
<listitem>
<para>This command expects a kernel version string as single argument. This calls executables from
<filename>/usr/lib/kernel/install.d/*.install</filename> and
<filename>/etc/kernel/install.d/*.install</filename> with the following arguments:
</para>
<para>This command expects a kernel version string as single argument.</para>
<para>The executable files from <filename>/usr/lib/kernel/install.d/*.install</filename> and
<filename>/etc/kernel/install.d/*.install</filename> (i.e. the plugins) are called with the
following arguments:</para>
<programlisting>remove <replaceable>KERNEL-VERSION</replaceable> <filename>$BOOT/<replaceable>ENTRY-TOKEN</replaceable>/<replaceable>KERNEL-VERSION</replaceable>/</filename></programlisting>
@ -150,13 +160,16 @@
<para>Two default plugins execute the following operations in this case:</para>
<itemizedlist>
<listitem><para><filename>50-depmod.install</filename> removes the files generated by <command>depmod</command> for this kernel again.</para></listitem>
<listitem><para><filename>50-depmod.install</filename> removes the files generated by
<command>depmod</command> for this kernel again.</para></listitem>
<listitem><para><filename>90-loaderentry.install</filename> removes the file
<filename>$BOOT/loader/entries/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.conf</filename>.</para></listitem>
<filename>$BOOT/loader/entries/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.conf</filename>.
</para></listitem>
<listitem><para><filename>90-uki-copy.install</filename> removes the file
<filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.efi</filename>.</para></listitem>
<filename>$BOOT/EFI/Linux/<replaceable>ENTRY-TOKEN</replaceable>-<replaceable>KERNEL-VERSION</replaceable>.efi</filename>.
</para></listitem>
</itemizedlist>
<xi:include href="version-info.xml" xpointer="v203"/>
@ -518,11 +531,16 @@
<filename>/etc/kernel/uki.conf</filename>
</term>
<listitem>
<para>Ini-style configuration file for <citerefentry><refentrytitle>ukify</refentrytitle><manvolnum>1</manvolnum></citerefentry> which is only effective when <varname>$KERNEL_INSTALL_LAYOUT</varname> or <varname>layout=</varname> in <filename>install.conf</filename> is set to <option>uki</option> and <varname>$KERNEL_INSTALL_UKI_GENERATOR</varname> or <varname>uki_generator=</varname> in <filename>install.conf</filename> is set to <option>ukify</option>.
<para>Ini-style configuration file for
<citerefentry><refentrytitle>ukify</refentrytitle><manvolnum>1</manvolnum></citerefentry> which
is only effective when <varname>$KERNEL_INSTALL_LAYOUT</varname> or <varname>layout=</varname> in
<filename>install.conf</filename> is set to <option>uki</option> and
<varname>$KERNEL_INSTALL_UKI_GENERATOR</varname> or <varname>uki_generator=</varname> in
<filename>install.conf</filename> is set to <option>ukify</option>.
<varname>$KERNEL_INSTALL_CONF_ROOT</varname> may be used to override the path.
</para>
<xi:include href="version-info.xml" xpointer="v255"/>
<xi:include href="version-info.xml" xpointer="v255"/>
</listitem>
</varlistentry>
</variablelist>

View file

@ -98,19 +98,80 @@
<title>Description</title>
<para><function>sd_notify()</function> may be called by a service to notify the service manager about
state changes. It can be used to send arbitrary information, encoded in an environment-block-like
string. Most importantly, it can be used for start-up completion notification.</para>
state changes. It can be used to send arbitrary information, encoded in an environment-block-like string.
Most importantly, it can be used for start-up or reload completion notifications.</para>
<para>If the <parameter>unset_environment</parameter> parameter is non-zero,
<function>sd_notify()</function> will unset the <varname>$NOTIFY_SOCKET</varname> environment variable
before returning (regardless of whether the function call itself succeeded or not). Further calls to
<function>sd_notify()</function> will then fail, but the variable is no longer inherited by child
<function>sd_notify()</function> will then fail, and the variable is no longer inherited by child
processes.</para>
<para>The <parameter>state</parameter> parameter should contain a newline-separated list of variable
assignments, similar in style to an environment block. A trailing newline is implied if none is
specified. The string may contain any kind of variable assignments, but the following shall be considered
well-known:</para>
specified. The string may contain any kind of variable assignments, but see the next section
for a list of assignments understood by the service manager.</para>
<para>Note that systemd will accept status data sent from a service only if the
<varname>NotifyAccess=</varname> option is correctly set in the service definition file. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para>
<para>Note that <function>sd_notify()</function> notifications may be attributed to units correctly only
if either the sending process is still around at the time PID 1 processes the message, or if the sending
process is explicitly runtime-tracked by the service manager. The latter is the case if the service
manager originally forked off the process, i.e. on all processes that match
<varname>NotifyAccess=</varname><option>main</option> or
<varname>NotifyAccess=</varname><option>exec</option>. Conversely, if an auxiliary process of the unit
sends an <function>sd_notify()</function> message and immediately exits, the service manager might not be
able to properly attribute the message to the unit, and thus will ignore it, even if
<varname>NotifyAccess=</varname><option>all</option> is set for it.</para>
<para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of
notifications to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as
a synchronization point and ensures all notifications sent before this call have been picked up by the
service manager when it returns successfully. Use of <function>sd_notify_barrier()</function> is needed
for clients which are not invoked by the service manager, otherwise this synchronization mechanism is
unnecessary for attribution of notifications to the unit.</para>
<para><function>sd_notifyf()</function> is similar to <function>sd_notify()</function> but takes a
<function>printf()</function>-like format string plus arguments.</para>
<para><function>sd_pid_notify()</function> and <function>sd_pid_notifyf()</function> are similar to
<function>sd_notify()</function> and <function>sd_notifyf()</function> but take a process ID (PID) to use
as originating PID for the message as first argument. This is useful to send notification messages on
behalf of other processes, provided the appropriate privileges are available. If the PID argument is
specified as 0, the process ID of the calling process is used, in which case the calls are fully
equivalent to <function>sd_notify()</function> and <function>sd_notifyf()</function>.</para>
<para><function>sd_pid_notify_with_fds()</function> is similar to <function>sd_pid_notify()</function>
but takes an additional array of file descriptors. These file descriptors are sent along the notification
message to the service manager. This is particularly useful for sending <literal>FDSTORE=1</literal>
messages, as described above. The additional arguments are a pointer to the file descriptor array plus
the number of file descriptors in the array. If the number of file descriptors is passed as 0, the call
is fully equivalent to <function>sd_pid_notify()</function>, i.e. no file descriptors are passed. Note
that file descriptors sent to the service manager on a message without <literal>FDSTORE=1</literal> are
immediately closed on reception.</para>
<para><function>sd_pid_notifyf_with_fds()</function> is a combination of
<function>sd_pid_notify_with_fds()</function> and <function>sd_notifyf()</function>, i.e. it accepts both
a PID and a set of file descriptors as input, and processes a format string to generate the state
string.</para>
<para><function>sd_notify_barrier()</function> allows the caller to synchronize against reception of
previously sent notification messages and uses the <varname>BARRIER=1</varname> command. It takes a
relative <varname>timeout</varname> value in microseconds which is passed to
<citerefentry><refentrytitle>ppoll</refentrytitle><manvolnum>2</manvolnum>
</citerefentry>. A value of UINT64_MAX is interpreted as infinite timeout.</para>
<para><function>sd_pid_notify_barrier()</function> is just like <function>sd_notify_barrier()</function>,
but allows specifying the originating PID for the notification message.</para>
</refsect1>
<refsect1>
<title>Well-known assignments</title>
<para>The following assignments have a defined meaning:</para>
<variablelist>
<varlistentry>
@ -126,9 +187,9 @@
<varlistentry>
<term>RELOADING=1</term>
<listitem><para>Tells the service manager that the service is beginning to reload its
configuration. This is useful to allow the service manager to track the service's internal state, and
present it to the user. Note that a service that sends this notification must also send a
<listitem><para>Tells the service manager that the service is beginning to reload its configuration.
This is useful to allow the service manager to track the service's internal state, and present it to
the user. Note that a service that sends this notification must also send a
<literal>READY=1</literal> notification when it completed reloading its configuration. Reloads the
service manager is notified about with this mechanisms are propagated in the same way as they are
when originally initiated through the service manager. This message is particularly relevant for
@ -138,6 +199,16 @@
<xi:include href="version-info.xml" xpointer="v217"/></listitem>
</varlistentry>
<varlistentry>
<term>STOPPING=1</term>
<listitem><para>Tells the service manager that the service is beginning its shutdown. This is useful
to allow the service manager to track the service's internal state, and present it to the user.
</para>
<xi:include href="version-info.xml" xpointer="v217"/></listitem>
</varlistentry>
<varlistentry>
<term>MONOTONIC_USEC=…</term>
@ -151,24 +222,13 @@
<xi:include href="version-info.xml" xpointer="v253"/></listitem>
</varlistentry>
<varlistentry>
<term>STOPPING=1</term>
<listitem><para>Tells the service manager that the service is beginning its shutdown. This is useful
to allow the service manager to track the service's internal state, and present it to the
user.</para>
<xi:include href="version-info.xml" xpointer="v217"/></listitem>
</varlistentry>
<varlistentry>
<term>STATUS=…</term>
<listitem><para>Passes a single-line UTF-8 status string back to the service manager that describes
the service state. This is free-form and can be used for various purposes: general state feedback,
fsck-like programs could pass completion percentages and failing programs could pass a human-readable
error message. Example: <literal>STATUS=Completed 66% of file system
check…</literal></para>
error message. Example: <literal>STATUS=Completed 66% of file system check…</literal></para>
<xi:include href="version-info.xml" xpointer="v233"/></listitem>
</varlistentry>
@ -179,8 +239,8 @@
<listitem><para>Reset the access to the service status notification socket during runtime, overriding
<varname>NotifyAccess=</varname> setting in the service unit file. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details, specifically <literal>NotifyAccess=</literal> for a list of accepted
values.</para>
for details, specifically <literal>NotifyAccess=</literal> for a list of accepted values.
</para>
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
</varlistentry>
@ -198,7 +258,8 @@
<term>BUSERROR=…</term>
<listitem><para>If a service fails, the D-Bus error-style error code. Example:
<literal>BUSERROR=org.freedesktop.DBus.Error.TimedOut</literal></para>
<literal>BUSERROR=org.freedesktop.DBus.Error.TimedOut</literal>. Note that this assignment is
currently not used by <command>systemd</command>.</para>
<xi:include href="version-info.xml" xpointer="v233"/></listitem>
</varlistentry>
@ -206,8 +267,15 @@
<varlistentry>
<term>EXIT_STATUS=…</term>
<listitem><para>If a service exits, the return value of its <function>main()</function> function.
</para>
<listitem><para>The exit status of a service or the manager itself. Note that
<command>systemd</command> currently does not consume this value when sent by services, so this
assignment is only informational. The manager will send this notification to <emphasis>its</emphasis>
notification socket, which may be used to to collect an exit status from the system (a container or
VM) as it shuts down. For example,
<citerefentry project='debian'><refentrytitle>mkosi</refentrytitle><manvolnum>1</manvolnum></citerefentry>
makes use of this. The value to return may be set via the
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<command>exit</command> verb.</para>
<xi:include href="version-info.xml" xpointer="v254"/></listitem>
</varlistentry>
@ -216,7 +284,7 @@
<term>MAINPID=…</term>
<listitem><para>The main process ID (PID) of the service, in case the service manager did not fork
off the process itself. Example: <literal>MAINPID=4711</literal></para>
off the process itself. Example: <literal>MAINPID=4711</literal>.</para>
<xi:include href="version-info.xml" xpointer="v233"/></listitem>
</varlistentry>
@ -276,29 +344,40 @@
<varlistentry>
<term>FDSTORE=1</term>
<listitem><para>Stores additional file descriptors in the service manager. File descriptors sent this
way will be maintained per-service by the service manager and will later be handed back using the
usual file descriptor passing logic at the next invocation of the service (e.g. when it is
restarted), see
<listitem><para>Store file descriptors in the service manager. File descriptors sent this way will be
held for the service by the service manager and will later be handed back using the usual file
descriptor passing logic at the next start or restart of the service, see
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
This is useful for implementing services that can restart after an explicit request or a crash
without losing state. Any open sockets and other file descriptors which should not be closed during
the restart may be stored this way. Application state can either be serialized to a file in
<filename>/run/</filename>, or better, stored in a
<citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
memory file descriptor. Note that the service manager will accept messages for a service only if its
Any open sockets and other file descriptors which should not be closed during a restart may be stored
this way. When a service is stopped, its file descriptor store is discarded and all file descriptors
in it are closed, except when overridden with <varname>FileDescriptorStorePreserve=</varname>, see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
<para>The service manager will accept messages for a service only if its
<varname>FileDescriptorStoreMax=</varname> setting is non-zero (defaults to zero, see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If
<varname>FDPOLL=0</varname> is not set and the file descriptors sent are pollable (see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
The service manager will set the <varname>$FDSTORE</varname> environment variable for services that
have the file descriptor store enabled, see
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para>
<para>If <varname>FDPOLL=0</varname> is not set and the file descriptors are pollable (see
<citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), then
any <constant>EPOLLHUP</constant> or <constant>EPOLLERR</constant> event seen on them will result in
their automatic removal from the store. Multiple arrays of file descriptors may be sent in separate
messages, in which case the arrays are combined. Note that the service manager removes duplicate
(pointing to the same object) file descriptors before passing them to the service. When a service is
stopped, its file descriptor store is discarded and all file descriptors in it are closed. Use
<function>sd_pid_notify_with_fds()</function> to send messages with <literal>FDSTORE=1</literal>, see
below. The service manager will set the <varname>$FDSTORE</varname> environment variable for services
that have the file descriptor store enabled.</para>
their automatic removal from the store.</para>
<para>Multiple sets of file descriptors may be sent in separate messages, in which case the sets are
combined. The service manager removes duplicate file descriptors (those pointing to the same object)
before passing them to the service.</para>
<para>This functionality should be used to implement services that can restart after an explicit
request or a crash without losing state. Application state can either be serialized to a file in
<filename>/run/</filename>, or better, stored in a
<citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>
memory file descriptor. Use <function>sd_pid_notify_with_fds()</function> to send messages with
<literal>FDSTORE=1</literal>. It is recommended to combine <varname>FDSTORE=</varname> with
<varname>FDNAME=</varname> to make it easier to manage the stored file descriptors.</para>
<para>For further information on the file descriptor store see the <ulink
url="https://systemd.io/FILE_DESCRIPTOR_STORE">File Descriptor Store</ulink> overview.</para>
@ -323,14 +402,16 @@
submitted file descriptors. When used with <varname>FDSTOREREMOVE=1</varname>, specifies the name for
the file descriptors to remove. This name is passed to the service during activation, and may be
queried using
<citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>. File
descriptors submitted without this field set, will implicitly get the name <literal>stored</literal>
assigned. Note that, if multiple file descriptors are submitted at once, the specified name will be
assigned to all of them. In order to assign different names to submitted file descriptors, submit
them in separate invocations of <function>sd_pid_notify_with_fds()</function>. The name may consist
of arbitrary ASCII characters except control characters or <literal>:</literal>. It may not be longer
than 255 characters. If a submitted name does not follow these restrictions, it is
ignored.</para>
<citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
File descriptors submitted without this field will be called <literal>stored</literal>.</para>
<para>The name may consist of arbitrary ASCII characters except control characters or
<literal>:</literal>. It may not be longer than 255 characters. If a submitted name does not follow
these restrictions, it is ignored.</para>
<para>Note that if multiple file descriptors are submitted in a single message, the specified name
will be used for all of them. In order to assign different names to submitted file descriptors,
submit them in separate messages.</para>
<xi:include href="version-info.xml" xpointer="v233"/></listitem>
</varlistentry>
@ -364,63 +445,10 @@
</varlistentry>
</variablelist>
<para>It is recommended to prefix variable names that are not listed above with <varname>X_</varname> to
avoid namespace clashes.</para>
<para>Note that systemd will accept status data sent from a service only if the
<varname>NotifyAccess=</varname> option is correctly set in the service definition file. See
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
details.</para>
<para>Note that <function>sd_notify()</function> notifications may be attributed to units correctly only
if either the sending process is still around at the time PID 1 processes the message, or if the sending
process is explicitly runtime-tracked by the service manager. The latter is the case if the service
manager originally forked off the process, i.e. on all processes that match
<varname>NotifyAccess=</varname><option>main</option> or
<varname>NotifyAccess=</varname><option>exec</option>. Conversely, if an auxiliary process of the unit
sends an <function>sd_notify()</function> message and immediately exits, the service manager might not be
able to properly attribute the message to the unit, and thus will ignore it, even if
<varname>NotifyAccess=</varname><option>all</option> is set for it.</para>
<para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of
notifications to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as
a synchronization point and ensures all notifications sent before this call have been picked up by the
service manager when it returns successfully. Use of <function>sd_notify_barrier()</function> is needed
for clients which are not invoked by the service manager, otherwise this synchronization mechanism is
unnecessary for attribution of notifications to the unit.</para>
<para><function>sd_notifyf()</function> is similar to <function>sd_notify()</function> but takes a
<function>printf()</function>-like format string plus arguments.</para>
<para><function>sd_pid_notify()</function> and <function>sd_pid_notifyf()</function> are similar to
<function>sd_notify()</function> and <function>sd_notifyf()</function> but take a process ID (PID) to use
as originating PID for the message as first argument. This is useful to send notification messages on
behalf of other processes, provided the appropriate privileges are available. If the PID argument is
specified as 0, the process ID of the calling process is used, in which case the calls are fully
equivalent to <function>sd_notify()</function> and <function>sd_notifyf()</function>.</para>
<para><function>sd_pid_notify_with_fds()</function> is similar to <function>sd_pid_notify()</function>
but takes an additional array of file descriptors. These file descriptors are sent along the notification
message to the service manager. This is particularly useful for sending <literal>FDSTORE=1</literal>
messages, as described above. The additional arguments are a pointer to the file descriptor array plus
the number of file descriptors in the array. If the number of file descriptors is passed as 0, the call
is fully equivalent to <function>sd_pid_notify()</function>, i.e. no file descriptors are passed. Note
that file descriptors sent to the service manager on a message without <literal>FDSTORE=1</literal> are
immediately closed on reception.</para>
<para><function>sd_pid_notifyf_with_fds()</function> is a combination of
<function>sd_pid_notify_with_fds()</function> and <function>sd_notifyf()</function>, i.e. it accepts both
a PID and a set of file descriptors as input, and processes a format string to generate the state
string.</para>
<para><function>sd_notify_barrier()</function> allows the caller to synchronize against reception of
previously sent notification messages and uses the <varname>BARRIER=1</varname> command. It takes a
relative <varname>timeout</varname> value in microseconds which is passed to
<citerefentry><refentrytitle>ppoll</refentrytitle><manvolnum>2</manvolnum>
</citerefentry>. A value of UINT64_MAX is interpreted as infinite timeout.</para>
<para><function>sd_pid_notify_barrier()</function> is just like <function>sd_notify_barrier()</function>,
but allows specifying the originating PID for the notification message.</para>
<para>The notification messages sent by services are interpreted by the service manager. Unknown
assignments may be logged, but are otherwise ignored. Thus, it is not useful to send assignments which
are not in this list. The service manager also sends some messages to <emphasis>its</emphasis>
notification socket, which are then consumed by the machine or container manager.</para>
</refsect1>
<refsect1>

View file

@ -3998,12 +3998,12 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
<varlistentry>
<term><varname>$FDSTORE</varname></term>
<listitem><para>If the file descriptor store is enabled for a service
(i.e. <varname>FileDescriptorStoreMax=</varname> is set to a non-zero value, see
<listitem><para>The maximum number of file descriptors that may be stored in the manager for the
service. This variable is set when the file descriptor store is enabled for the service, i.e.
<varname>FileDescriptorStoreMax=</varname> is set to a non-zero value (see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details), this environment variable will be set to the maximum number of permitted entries, as
per the setting. Applications may check this environment variable before sending file descriptors
to the service manager via <function>sd_pid_notify_with_fds()</function> (see
for details). Applications may check this environment variable before sending file descriptors to
the service manager via <function>sd_pid_notify_with_fds()</function> (see
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> for
details).</para>