Merge pull request #25916 from poettering/reload-notify
pid1: add new Type=notify-reload service type for a service reload protocol based on SIGHUP
This commit is contained in:
@@ -763,17 +763,9 @@ Features:
|
||||
and synthesize initrd from it, and measure it. Signing is not necessary, as
|
||||
microcode does that on its own. Pass as first initrd to kernel.
|
||||
|
||||
* Add a new service type very similar to Type=notify, that goes one step
|
||||
further and extends the protocol to cover reloads. Specifically, SIGHUP will
|
||||
become the official way to reload, and daemon has to respond with sd_notify()
|
||||
to report when it starts reloading, and when it is complete reloading. Care
|
||||
must be taken to remove races from this model. I.e. PID 1 needs to take
|
||||
CLOCK_MONOTONIC, then send SIGHUP, then wait for at least one RELOADING=1
|
||||
message that comes with a newer timestamp, then wait for a READY=1 message.
|
||||
while we are at it, also maybe extend the logic to require handling of some
|
||||
specific SIGRT signal for setting debug log level, that carries the level via
|
||||
the sigqueue() data parameter. With that we extended with minimal logic the
|
||||
service runtime logic quite substantially.
|
||||
* Maybe extend the service protocol to support handling of some specific SIGRT
|
||||
signal for setting service log level, that carries the level via the
|
||||
sigqueue() data parameter. Enable this via unit file setting.
|
||||
|
||||
* firstboot: maybe just default to C.UTF-8 locale if nothing is set, so that we
|
||||
don't query this unnecessarily in entirely uninitialized
|
||||
@@ -1774,7 +1766,6 @@ Features:
|
||||
* unit files:
|
||||
- allow port=0 in .socket units
|
||||
- maybe introduce ExecRestartPre=
|
||||
- add ReloadSignal= for configuring a reload signal to use
|
||||
- implement Register= switch in .socket units to enable registration
|
||||
in Avahi, RPC and other socket registration services.
|
||||
- allow Type=simple with PIDFile=
|
||||
|
||||
@@ -2578,6 +2578,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
readonly s OOMPolicy = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly a(sst) OpenFile = [...];
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly i ReloadSignal = ...;
|
||||
readonly t ExecMainStartTimestamp = ...;
|
||||
readonly t ExecMainStartTimestampMonotonic = ...;
|
||||
readonly t ExecMainExitTimestamp = ...;
|
||||
@@ -3177,6 +3179,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<!--property OpenFile is not documented!-->
|
||||
|
||||
<!--property ReloadSignal is not documented!-->
|
||||
|
||||
<!--property ExecCondition is not documented!-->
|
||||
|
||||
<!--property ExecConditionEx is not documented!-->
|
||||
@@ -3735,6 +3739,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="OpenFile"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ReloadSignal"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ExecMainStartTimestamp"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ExecMainStartTimestampMonotonic"/>
|
||||
|
||||
+24
-12
@@ -102,23 +102,35 @@
|
||||
<varlistentry>
|
||||
<term>READY=1</term>
|
||||
|
||||
<listitem><para>Tells the service manager that service startup is finished, or the service finished loading its
|
||||
configuration. This is only used by systemd if the service definition file has <varname>Type=notify</varname>
|
||||
set. Since there is little value in signaling non-readiness, the only value services should send is
|
||||
<literal>READY=1</literal> (i.e. <literal>READY=0</literal> is not defined).</para></listitem>
|
||||
<listitem><para>Tells the service manager that service startup is finished, or the service finished
|
||||
re-loading its configuration. This is only used by systemd if the service definition file has
|
||||
<varname>Type=notify</varname> or <varname>Type=notify-reload</varname> set. Since there is little
|
||||
value in signaling non-readiness, the only value services should send is <literal>READY=1</literal>
|
||||
(i.e. <literal>READY=0</literal> is not defined).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>RELOADING=1</term>
|
||||
|
||||
<listitem><para>Tells the service manager that the service is
|
||||
reloading 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 are propagated in the same way as they
|
||||
are when initiated by the user.</para></listitem>
|
||||
<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
|
||||
<varname>Type=notify-reload</varname> services, to inform the service manager that the request to
|
||||
reload the service has been received and is now being processed.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>MONOTONIC_USEC=…</term>
|
||||
|
||||
<listitem><para>A field carrying the monotonic timestamp (as per
|
||||
<constant>CLOCK_MONOTONIC</constant>) formatted in decimal in µs, when the notification message was
|
||||
generated by the client. This is typically used in combination with <literal>RELOADING=1</literal>,
|
||||
to allow the service manager to properly synchronize reload cycles. See
|
||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details, specifically <literal>Type=notify-reload</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
||||
+51
-36
@@ -30,20 +30,18 @@
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para><command>systemd-notify</command> may be called by daemon
|
||||
scripts to notify the init system about status changes. It can be
|
||||
used to send arbitrary information, encoded in an
|
||||
environment-block-like list of strings. Most importantly, it can be
|
||||
used for start-up completion notification.</para>
|
||||
<para><command>systemd-notify</command> may be called by service scripts to notify the invoking service
|
||||
manager about status changes. It can be used to send arbitrary information, encoded in an
|
||||
environment-block-like list of strings. Most importantly, it can be used for start-up completion
|
||||
notification.</para>
|
||||
|
||||
<para>This is mostly just a wrapper around
|
||||
<function>sd_notify()</function> and makes this functionality
|
||||
<para>This is mostly just a wrapper around <function>sd_notify()</function> and makes this functionality
|
||||
available to shell scripts. For details see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<para>The command line may carry a list of environment variables
|
||||
to send as part of the status update.</para>
|
||||
<para>The command line may carry a list of environment variables to send as part of the status
|
||||
update.</para>
|
||||
|
||||
<para>Note that systemd will refuse reception of status updates from this command unless
|
||||
<varname>NotifyAccess=</varname> is appropriately set for the service unit this command is called
|
||||
@@ -52,9 +50,9 @@
|
||||
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
|
||||
if either the sending process is still around at the time the service manager 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
|
||||
@@ -84,22 +82,42 @@
|
||||
<varlistentry>
|
||||
<term><option>--ready</option></term>
|
||||
|
||||
<listitem><para>Inform the init system about service start-up
|
||||
completion. This is equivalent to <command>systemd-notify
|
||||
READY=1</command>. For details about the semantics of this
|
||||
option see
|
||||
<listitem><para>Inform the invoking service manager about service start-up or configuration reload
|
||||
completion. This is equivalent to <command>systemd-notify READY=1</command>. For details about the
|
||||
semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--reloading</option></term>
|
||||
|
||||
<listitem><para>Inform the invoking service manager about the beginning of a configuration reload
|
||||
cycle. This is equivalent to <command>systemd-notify RELOADING=1</command> (but implicitly also sets
|
||||
a <varname>MONOTONIC_USEC=</varname> field as required for <varname>Type=notify-reload</varname>
|
||||
services, see
|
||||
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
for details). For details about the semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--stopping</option></term>
|
||||
|
||||
<listitem><para>Inform the invoking service manager about the beginning of the shutdown phase of the
|
||||
service. This is equivalent to <command>systemd-notify STOPPING=1</command>. For details about the
|
||||
semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--pid=</option></term>
|
||||
|
||||
<listitem><para>Inform the service manager about the main PID of the daemon. Takes a PID as
|
||||
<listitem><para>Inform the service manager about the main PID of the service. Takes a PID as
|
||||
argument. If the argument is specified as <literal>auto</literal> or omitted, the PID of the process
|
||||
that invoked <command>systemd-notify</command> is used, except if that's the service manager. If the
|
||||
argument is specified as <literal>self</literal>, the PID of the <command>systemd-notify</command>
|
||||
command itself is used, and if <literal>parent</literal> is specified the calling process' PID is
|
||||
used — even if it is the service manager. This is equivalent to <command>systemd-notify
|
||||
used — even if it is the service manager. The latter is equivalent to <command>systemd-notify
|
||||
MAINPID=$PID</command>. For details about the semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para>
|
||||
|
||||
@@ -124,27 +142,26 @@
|
||||
<varlistentry>
|
||||
<term><option>--status=</option></term>
|
||||
|
||||
<listitem><para>Send a free-form status string for the daemon
|
||||
to the init systemd. This option takes the status string as
|
||||
argument. This is equivalent to <command>systemd-notify
|
||||
STATUS=…</command>. For details about the semantics of this
|
||||
option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
<listitem><para>Send a free-form human readable status string for the daemon to the service
|
||||
manager. This option takes the status string as argument. This is equivalent to
|
||||
<command>systemd-notify STATUS=…</command>. For details about the semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
|
||||
information is shown in
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>status</command> output, among other places.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--booted</option></term>
|
||||
|
||||
<listitem><para>Returns 0 if the system was booted up with
|
||||
systemd, non-zero otherwise. If this option is passed, no
|
||||
message is sent. This option is hence unrelated to the other
|
||||
options. For details about the semantics of this option, see
|
||||
<listitem><para>Returns 0 if the system was booted up with systemd, non-zero otherwise. If this
|
||||
option is passed, no message is sent. This option is hence unrelated to the other options. For
|
||||
details about the semantics of this option, see
|
||||
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>. An
|
||||
alternate way to check for this state is to call
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
with the <command>is-system-running</command> command. It will
|
||||
return <literal>offline</literal> if the system was not booted
|
||||
with systemd. </para></listitem>
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> with
|
||||
the <command>is-system-running</command> command. It will return <literal>offline</literal> if the
|
||||
system was not booted with systemd. </para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -176,9 +193,8 @@
|
||||
<example>
|
||||
<title>Start-up Notification and Status Updates</title>
|
||||
|
||||
<para>A simple shell daemon that sends start-up notifications
|
||||
after having set up its communication channel. During runtime it
|
||||
sends further status updates to the init system:</para>
|
||||
<para>A simple shell daemon that sends start-up notifications after having set up its communication
|
||||
channel. During runtime it sends further status updates to the init system:</para>
|
||||
|
||||
<programlisting>#!/bin/sh
|
||||
|
||||
@@ -207,5 +223,4 @@ done</programlisting>
|
||||
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
+138
-110
@@ -157,7 +157,7 @@
|
||||
<listitem>
|
||||
<para>Configures the process start-up type for this service unit. One of <option>simple</option>,
|
||||
<option>exec</option>, <option>forking</option>, <option>oneshot</option>, <option>dbus</option>,
|
||||
<option>notify</option> or <option>idle</option>:</para>
|
||||
<option>notify</option>, <option>notify-reload</option> or <option>idle</option>:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>If set to <option>simple</option> (the default if <varname>ExecStart=</varname> is
|
||||
@@ -216,14 +216,30 @@
|
||||
logic thus should be prepared to receive a <constant>SIGTERM</constant> (or whichever signal is
|
||||
configured in <varname>KillSignal=</varname>) as result.</para></listitem>
|
||||
|
||||
<listitem><para>Behavior of <option>notify</option> is similar to <option>exec</option>; however, it is
|
||||
expected that the service sends a notification message via
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> or an
|
||||
equivalent call when it has finished starting up. systemd will proceed with starting follow-up units after
|
||||
this notification message has been sent. If this option is used, <varname>NotifyAccess=</varname> (see
|
||||
below) should be set to open access to the notification socket provided by systemd. If
|
||||
<varname>NotifyAccess=</varname> is missing or set to <option>none</option>, it will be forcibly set to
|
||||
<option>main</option>.</para></listitem>
|
||||
<listitem><para>Behavior of <option>notify</option> is similar to <option>exec</option>; however,
|
||||
it is expected that the service sends a <literal>READY=1</literal> notification message via
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> or
|
||||
an equivalent call when it has finished starting up. systemd will proceed with starting follow-up
|
||||
units after this notification message has been sent. If this option is used,
|
||||
<varname>NotifyAccess=</varname> (see below) should be set to open access to the notification
|
||||
socket provided by systemd. If <varname>NotifyAccess=</varname> is missing or set to
|
||||
<option>none</option>, it will be forcibly set to <option>main</option>.</para></listitem>
|
||||
|
||||
<listitem><para>Behavior of <option>notify-reload</option> is identical to
|
||||
<option>notify</option>. However, it extends the logic in one way: the
|
||||
<constant>SIGHUP</constant> UNIX process signal is sent to the service's main process when the
|
||||
service is asked to reload. (The signal to send can be tweaked via
|
||||
<varname>ReloadSignal=</varname>, see below.). When
|
||||
initiating the reload process the service is then expected to reply with a notification message
|
||||
via <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
that contains the <literal>RELOADING=1</literal> field in combination with
|
||||
<literal>MONOTONIC_USEC=</literal> set to the current monotonic time
|
||||
(i.e. <constant>CLOCK_MONOTONIC</constant> in
|
||||
<citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>)
|
||||
in µs, formatted as decimal string. Once reloading is complete another notification message must
|
||||
be sent, containing <literal>READY=1</literal>. Using this service type and implementing this
|
||||
reload protocol is an efficient alternative to providing an <varname>ExecReload=</varname>
|
||||
command for reloading of the service's configuration.</para></listitem>
|
||||
|
||||
<listitem><para>Behavior of <option>idle</option> is very similar to <option>simple</option>; however,
|
||||
actual execution of the service program is delayed until all active jobs are dispatched. This may be used
|
||||
@@ -233,25 +249,27 @@
|
||||
anyway.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>It is generally recommended to use <varname>Type=</varname><option>simple</option> for long-running
|
||||
services whenever possible, as it is the simplest and fastest option. However, as this service type won't
|
||||
propagate service start-up failures and doesn't allow ordering of other units against completion of
|
||||
initialization of the service (which for example is useful if clients need to connect to the service through
|
||||
some form of IPC, and the IPC channel is only established by the service itself — in contrast to doing this
|
||||
ahead of time through socket or bus activation or similar), it might not be sufficient for many cases. If so,
|
||||
<option>notify</option> or <option>dbus</option> (the latter only in case the service provides a D-Bus
|
||||
interface) are the preferred options as they allow service program code to precisely schedule when to
|
||||
consider the service started up successfully and when to proceed with follow-up units. The
|
||||
<option>notify</option> service type requires explicit support in the service codebase (as
|
||||
<function>sd_notify()</function> or an equivalent API needs to be invoked by the service at the appropriate
|
||||
time) — if it's not supported, then <option>forking</option> is an alternative: it supports the traditional
|
||||
UNIX service start-up protocol. Finally, <option>exec</option> might be an option for cases where it is
|
||||
enough to ensure the service binary is invoked, and where the service binary itself executes no or little
|
||||
initialization on its own (and its initialization is unlikely to fail). Note that using any type other than
|
||||
<option>simple</option> possibly delays the boot process, as the service manager needs to wait for service
|
||||
initialization to complete. It is hence recommended not to needlessly use any types other than
|
||||
<option>simple</option>. (Also note it is generally not recommended to use <option>idle</option> or
|
||||
<option>oneshot</option> for long-running services.)</para>
|
||||
<para>It is generally recommended to use <varname>Type=</varname><option>simple</option> for
|
||||
long-running services whenever possible, as it is the simplest and fastest option. However, as this
|
||||
service type won't propagate service start-up failures and doesn't allow ordering of other units
|
||||
against completion of initialization of the service (which for example is useful if clients need to
|
||||
connect to the service through some form of IPC, and the IPC channel is only established by the
|
||||
service itself — in contrast to doing this ahead of time through socket or bus activation or
|
||||
similar), it might not be sufficient for many cases. If so, <option>notify</option>,
|
||||
<option>notify-reload</option> or <option>dbus</option> (the latter only in case the service
|
||||
provides a D-Bus interface) are the preferred options as they allow service program code to
|
||||
precisely schedule when to consider the service started up successfully and when to proceed with
|
||||
follow-up units. The <option>notify</option>/<option>notify-reload</option> service types require
|
||||
explicit support in the service codebase (as <function>sd_notify()</function> or an equivalent API
|
||||
needs to be invoked by the service at the appropriate time) — if it's not supported, then
|
||||
<option>forking</option> is an alternative: it supports the traditional UNIX service start-up
|
||||
protocol. Finally, <option>exec</option> might be an option for cases where it is enough to ensure
|
||||
the service binary is invoked, and where the service binary itself executes no or little
|
||||
initialization on its own (and its initialization is unlikely to fail). Note that using any type
|
||||
other than <option>simple</option> possibly delays the boot process, as the service manager needs
|
||||
to wait for service initialization to complete. It is hence recommended not to needlessly use any
|
||||
types other than <option>simple</option>. (Also note it is generally not recommended to use
|
||||
<option>idle</option> or <option>oneshot</option> for long-running services.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -319,9 +337,10 @@
|
||||
the file may not be a symlink to a file owned by a different user (neither directly nor indirectly), and the
|
||||
PID file must refer to a process already belonging to the service.</para>
|
||||
|
||||
<para>Note that PID files should be avoided in modern projects. Use <option>Type=notify</option> or
|
||||
<option>Type=simple</option> where possible, which does not require use of PID files to determine the
|
||||
main process of a service and avoids needless forking.</para></listitem>
|
||||
<para>Note that PID files should be avoided in modern projects. Use <option>Type=notify</option>,
|
||||
<option>Type=notify-reload</option> or <option>Type=simple</option> where possible, which does not
|
||||
require use of PID files to determine the main process of a service and avoids needless
|
||||
forking.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -443,12 +462,13 @@
|
||||
with a <literal>-</literal> exit successfully.</para>
|
||||
|
||||
<para><varname>ExecStartPost=</varname> commands are only run after the commands specified in
|
||||
<varname>ExecStart=</varname> have been invoked successfully, as determined by <varname>Type=</varname>
|
||||
(i.e. the process has been started for <varname>Type=simple</varname> or <varname>Type=idle</varname>, the last
|
||||
<varname>ExecStart=</varname> process exited successfully for <varname>Type=oneshot</varname>, the initial
|
||||
process exited successfully for <varname>Type=forking</varname>, <literal>READY=1</literal> is sent for
|
||||
<varname>Type=notify</varname>, or the <varname>BusName=</varname> has been taken for
|
||||
<varname>Type=dbus</varname>).</para>
|
||||
<varname>ExecStart=</varname> have been invoked successfully, as determined by
|
||||
<varname>Type=</varname> (i.e. the process has been started for <varname>Type=simple</varname> or
|
||||
<varname>Type=idle</varname>, the last <varname>ExecStart=</varname> process exited successfully for
|
||||
<varname>Type=oneshot</varname>, the initial process exited successfully for
|
||||
<varname>Type=forking</varname>, <literal>READY=1</literal> is sent for
|
||||
<varname>Type=notify</varname>/<varname>Type=notify-reload</varname>, or the
|
||||
<varname>BusName=</varname> has been taken for <varname>Type=dbus</varname>).</para>
|
||||
|
||||
<para>Note that <varname>ExecStartPre=</varname> may not be
|
||||
used to start long-running processes. All processes forked
|
||||
@@ -487,30 +507,26 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ExecReload=</varname></term>
|
||||
<listitem><para>Commands to execute to trigger a configuration
|
||||
reload in the service. This argument takes multiple command
|
||||
lines, following the same scheme as described for
|
||||
<varname>ExecStart=</varname> above. Use of this setting is
|
||||
optional. Specifier and environment variable substitution is
|
||||
supported here following the same scheme as for
|
||||
|
||||
<listitem><para>Commands to execute to trigger a configuration reload in the service. This argument
|
||||
takes multiple command lines, following the same scheme as described for
|
||||
<varname>ExecStart=</varname> above. Use of this setting is optional. Specifier and environment
|
||||
variable substitution is supported here following the same scheme as for
|
||||
<varname>ExecStart=</varname>.</para>
|
||||
|
||||
<para>One additional, special environment variable is set: if
|
||||
known, <varname>$MAINPID</varname> is set to the main process
|
||||
of the daemon, and may be used for command lines like the
|
||||
following:</para>
|
||||
<para>One additional, special environment variable is set: if known, <varname>$MAINPID</varname> is
|
||||
set to the main process of the daemon, and may be used for command lines like the following:</para>
|
||||
|
||||
<programlisting>ExecReload=kill -HUP $MAINPID</programlisting>
|
||||
|
||||
<para>Note however that reloading a daemon by sending a signal
|
||||
(as with the example line above) is usually not a good choice,
|
||||
because this is an asynchronous operation and hence not
|
||||
suitable to order reloads of multiple services against each
|
||||
other. It is strongly recommended to set
|
||||
<varname>ExecReload=</varname> to a command that not only
|
||||
triggers a configuration reload of the daemon, but also
|
||||
synchronously waits for it to complete. For example,
|
||||
<citerefentry project='mankier'><refentrytitle>dbus-broker</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
<para>Note however that reloading a daemon by enqueing a signal (as with the example line above) is
|
||||
usually not a good choice, because this is an asynchronous operation and hence not suitable when
|
||||
ordering reloads of multiple services against each other. It is thus strongly recommended to either
|
||||
use <varname>Type=</varname><option>notify-reload</option> in place of
|
||||
<varname>ExecReload=</varname>, or to set <varname>ExecReload=</varname> to a command that not only
|
||||
triggers a configuration reload of the daemon, but also synchronously waits for it to complete. For
|
||||
example, <citerefentry
|
||||
project='mankier'><refentrytitle>dbus-broker</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
uses the following:</para>
|
||||
|
||||
<programlisting>ExecReload=busctl call org.freedesktop.DBus \
|
||||
@@ -605,12 +621,13 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
<para>If a service of <varname>Type=notify</varname> sends <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause
|
||||
the start time to be extended beyond <varname>TimeoutStartSec=</varname>. The first receipt of this message
|
||||
must occur before <varname>TimeoutStartSec=</varname> is exceeded, and once the start time has extended beyond
|
||||
<varname>TimeoutStartSec=</varname>, the service manager will allow the service to continue to start, provided
|
||||
the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified until the service
|
||||
startup status is finished by <literal>READY=1</literal>. (see
|
||||
<para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> sends
|
||||
<literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause the start time to be extended beyond
|
||||
<varname>TimeoutStartSec=</varname>. The first receipt of this message must occur before
|
||||
<varname>TimeoutStartSec=</varname> is exceeded, and once the start time has extended beyond
|
||||
<varname>TimeoutStartSec=</varname>, the service manager will allow the service to continue to start,
|
||||
provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified
|
||||
until the service startup status is finished by <literal>READY=1</literal>. (see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
@@ -633,12 +650,14 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
<para>If a service of <varname>Type=notify</varname> sends <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause
|
||||
the stop time to be extended beyond <varname>TimeoutStopSec=</varname>. The first receipt of this message
|
||||
must occur before <varname>TimeoutStopSec=</varname> is exceeded, and once the stop time has extended beyond
|
||||
<varname>TimeoutStopSec=</varname>, the service manager will allow the service to continue to stop, provided
|
||||
the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified, or terminates itself
|
||||
(see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
<para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> sends
|
||||
<literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause the stop time to be extended beyond
|
||||
<varname>TimeoutStopSec=</varname>. The first receipt of this message must occur before
|
||||
<varname>TimeoutStopSec=</varname> is exceeded, and once the stop time has extended beyond
|
||||
<varname>TimeoutStopSec=</varname>, the service manager will allow the service to continue to stop,
|
||||
provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified,
|
||||
or terminates itself (see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -661,13 +680,15 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
<para>If a service of <varname>Type=notify</varname> handles <constant>SIGABRT</constant> itself (instead of relying
|
||||
on the kernel to write a core dump) it can send <literal>EXTEND_TIMEOUT_USEC=…</literal> to
|
||||
extended the abort time beyond <varname>TimeoutAbortSec=</varname>. The first receipt of this message
|
||||
must occur before <varname>TimeoutAbortSec=</varname> is exceeded, and once the abort time has extended beyond
|
||||
<varname>TimeoutAbortSec=</varname>, the service manager will allow the service to continue to abort, provided
|
||||
the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified, or terminates itself
|
||||
(see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
<para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> handles
|
||||
<constant>SIGABRT</constant> itself (instead of relying on the kernel to write a core dump) it can
|
||||
send <literal>EXTEND_TIMEOUT_USEC=…</literal> to extended the abort time beyond
|
||||
<varname>TimeoutAbortSec=</varname>. The first receipt of this message must occur before
|
||||
<varname>TimeoutAbortSec=</varname> is exceeded, and once the abort time has extended beyond
|
||||
<varname>TimeoutAbortSec=</varname>, the service manager will allow the service to continue to abort,
|
||||
provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified,
|
||||
or terminates itself (see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -710,12 +731,13 @@
|
||||
activation completed. Pass <literal>infinity</literal> (the default) to configure no runtime
|
||||
limit.</para>
|
||||
|
||||
<para>If a service of <varname>Type=notify</varname> sends <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause
|
||||
the runtime to be extended beyond <varname>RuntimeMaxSec=</varname>. The first receipt of this message
|
||||
must occur before <varname>RuntimeMaxSec=</varname> is exceeded, and once the runtime has extended beyond
|
||||
<varname>RuntimeMaxSec=</varname>, the service manager will allow the service to continue to run, provided
|
||||
the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified until the service
|
||||
shutdown is achieved by <literal>STOPPING=1</literal> (or termination). (see
|
||||
<para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> sends
|
||||
<literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause the runtime to be extended beyond
|
||||
<varname>RuntimeMaxSec=</varname>. The first receipt of this message must occur before
|
||||
<varname>RuntimeMaxSec=</varname> is exceeded, and once the runtime has extended beyond
|
||||
<varname>RuntimeMaxSec=</varname>, the service manager will allow the service to continue to run,
|
||||
provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified
|
||||
until the service shutdown is achieved by <literal>STOPPING=1</literal> (or termination). (see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
@@ -1023,16 +1045,19 @@
|
||||
<varlistentry>
|
||||
<term><varname>NotifyAccess=</varname></term>
|
||||
<listitem><para>Controls access to the service status notification socket, as accessible via the
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> call. Takes one
|
||||
of <option>none</option> (the default), <option>main</option>, <option>exec</option> or
|
||||
<option>all</option>. If <option>none</option>, no daemon status updates are accepted from the service
|
||||
processes, all status update messages are ignored. If <option>main</option>, only service updates sent from the
|
||||
main process of the service are accepted. If <option>exec</option>, only service updates sent from any of the
|
||||
main or control processes originating from one of the <varname>Exec*=</varname> commands are accepted. If
|
||||
<option>all</option>, all services updates from all members of the service's control group are accepted. This
|
||||
option should be set to open access to the notification socket when using <varname>Type=notify</varname> or
|
||||
<varname>WatchdogSec=</varname> (see above). If those options are used but <varname>NotifyAccess=</varname> is
|
||||
not configured, it will be implicitly set to <option>main</option>.</para>
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
call. Takes one of <option>none</option> (the default), <option>main</option>, <option>exec</option>
|
||||
or <option>all</option>. If <option>none</option>, no daemon status updates are accepted from the
|
||||
service processes, all status update messages are ignored. If <option>main</option>, only service
|
||||
updates sent from the main process of the service are accepted. If <option>exec</option>, only
|
||||
service updates sent from any of the main or control processes originating from one of the
|
||||
<varname>Exec*=</varname> commands are accepted. If <option>all</option>, all services updates from
|
||||
all members of the service's control group are accepted. This option should be set to open access to
|
||||
the notification socket when using
|
||||
<varname>Type=notify</varname>/<varname>Type=notify-reload</varname> or
|
||||
<varname>WatchdogSec=</varname> (see above). If those options are used but
|
||||
<varname>NotifyAccess=</varname> is not configured, it will be implicitly set to
|
||||
<option>main</option>.</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
|
||||
@@ -1156,6 +1181,7 @@
|
||||
kills, this setting determines the state of the unit after <command>systemd-oomd</command> kills a
|
||||
cgroup associated with it.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>OpenFile=</varname></term>
|
||||
<listitem><para>Takes an argument of the form <literal>path<optional><replaceable>:fd-name:options</replaceable></optional></literal>,
|
||||
@@ -1187,6 +1213,14 @@
|
||||
If the empty string is assigned, the entire list of open files defined prior to this is reset.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ReloadSignal=</varname></term>
|
||||
<listitem><para>Configures the UNIX process signal to send to the service's main process when asked
|
||||
to reload the service's configuration. Defaults to <constant>SIGHUP</constant>. This option has no
|
||||
effect unless <varname>Type=</varname><option>notify-reload</option> is used, see
|
||||
above.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para id='shared-unit-options'>Check
|
||||
@@ -1350,16 +1384,13 @@ WantedBy=multi-user.target</programlisting>
|
||||
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
|
||||
<para>Note that this unit type does not include any type of
|
||||
notification when a service has completed initialization. For
|
||||
this, you should use other unit types, such as
|
||||
<varname>Type=</varname><option>notify</option> if the service
|
||||
understands systemd's notification protocol,
|
||||
<varname>Type=</varname><option>forking</option> if the service
|
||||
can background itself or
|
||||
<varname>Type=</varname><option>dbus</option> if the unit
|
||||
acquires a DBus name once initialization is complete. See
|
||||
below.</para>
|
||||
<para>Note that this unit type does not include any type of notification when a service has completed
|
||||
initialization. For this, you should use other unit types, such as
|
||||
<varname>Type=</varname><option>notify</option>/<varname>Type=</varname><option>notify-reload</option>
|
||||
if the service understands systemd's notification protocol,
|
||||
<varname>Type=</varname><option>forking</option> if the service can background itself or
|
||||
<varname>Type=</varname><option>dbus</option> if the unit acquires a DBus name once initialization is
|
||||
complete. See below.</para>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
@@ -1536,15 +1567,12 @@ SystemdService=simple-dbus-service.service</programlisting>
|
||||
<example>
|
||||
<title>Services that notify systemd about their initialization</title>
|
||||
|
||||
<para><varname>Type=</varname><option>simple</option> services
|
||||
are really easy to write, but have the major disadvantage of
|
||||
systemd not being able to tell when initialization of the given
|
||||
service is complete. For this reason, systemd supports a simple
|
||||
notification protocol that allows daemons to make systemd aware
|
||||
that they are done initializing. Use
|
||||
<varname>Type=</varname><option>notify</option> for this. A
|
||||
typical service file for such a daemon would look like
|
||||
this:</para>
|
||||
<para><varname>Type=</varname><option>simple</option> services are really easy to write, but have the
|
||||
major disadvantage of systemd not being able to tell when initialization of the given service is
|
||||
complete. For this reason, systemd supports a simple notification protocol that allows daemons to make
|
||||
systemd aware that they are done initializing. Use <varname>Type=</varname><option>notify</option> or
|
||||
<varname>Type=</varname><option>notify-reload</option> for this. A typical service file for such a
|
||||
daemon would look like this:</para>
|
||||
|
||||
<programlisting>[Unit]
|
||||
Description=Simple notifying service
|
||||
|
||||
@@ -188,6 +188,8 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_RUNNING] = "running",
|
||||
[SERVICE_EXITED] = "exited",
|
||||
[SERVICE_RELOAD] = "reload",
|
||||
[SERVICE_RELOAD_SIGNAL] = "reload-signal",
|
||||
[SERVICE_RELOAD_NOTIFY] = "reload-notify",
|
||||
[SERVICE_STOP] = "stop",
|
||||
[SERVICE_STOP_WATCHDOG] = "stop-watchdog",
|
||||
[SERVICE_STOP_SIGTERM] = "stop-sigterm",
|
||||
|
||||
@@ -132,7 +132,9 @@ typedef enum ServiceState {
|
||||
SERVICE_START_POST,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_RELOAD, /* Reloading via ExecReload= */
|
||||
SERVICE_RELOAD_SIGNAL, /* Reloading via SIGHUP requested */
|
||||
SERVICE_RELOAD_NOTIFY, /* Waiting for READY=1 after RELOADING=1 notify */
|
||||
SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */
|
||||
SERVICE_STOP_WATCHDOG,
|
||||
SERVICE_STOP_SIGTERM,
|
||||
|
||||
@@ -258,6 +258,7 @@ const sd_bus_vtable bus_service_vtable[] = {
|
||||
SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
SD_BUS_PROPERTY("OOMPolicy", "s", bus_property_get_oom_policy, offsetof(Service, oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("OpenFile", "a(sst)", property_get_open_files, offsetof(Service, open_files), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ReloadSignal", "i", bus_property_get_int, offsetof(Service, reload_signal), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
|
||||
BUS_EXEC_COMMAND_LIST_VTABLE("ExecCondition", offsetof(Service, exec_command[SERVICE_EXEC_CONDITION]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
|
||||
@@ -404,6 +405,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_r
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
|
||||
static BUS_DEFINE_SET_TRANSIENT_PARSE(timeout_failure_mode, ServiceTimeoutFailureMode, service_timeout_failure_mode_from_string);
|
||||
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(reload_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check);
|
||||
|
||||
static int bus_service_set_transient_property(
|
||||
Service *s,
|
||||
@@ -612,6 +614,9 @@ static int bus_service_set_transient_property(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (streq(name, "ReloadSignal"))
|
||||
return bus_set_transient_reload_signal(u, name, &s->reload_signal, message, flags, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -427,6 +427,7 @@ Service.USBFunctionDescriptors, config_parse_unit_path_printf,
|
||||
Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings)
|
||||
Service.OOMPolicy, config_parse_oom_policy, 0, offsetof(Service, oom_policy)
|
||||
Service.OpenFile, config_parse_open_file, 0, offsetof(Service, open_files)
|
||||
Service.ReloadSignal, config_parse_signal, 0, offsetof(Service, reload_signal)
|
||||
{{ EXEC_CONTEXT_CONFIG_ITEMS('Service') }}
|
||||
{{ CGROUP_CONTEXT_CONFIG_ITEMS('Service') }}
|
||||
{{ KILL_CONTEXT_CONFIG_ITEMS('Service') }}
|
||||
|
||||
@@ -1961,6 +1961,8 @@ static int invoke_main_loop(
|
||||
LogTarget saved_log_target;
|
||||
int saved_log_level;
|
||||
|
||||
manager_send_reloading(m);
|
||||
|
||||
log_info("Reloading.");
|
||||
|
||||
/* First, save any overridden log level/target, then parse the configuration file,
|
||||
@@ -1991,6 +1993,10 @@ static int invoke_main_loop(
|
||||
}
|
||||
|
||||
case MANAGER_REEXECUTE:
|
||||
|
||||
manager_send_reloading(m); /* From the perspective of the manager calling us this is
|
||||
* pretty much the same as a reload */
|
||||
|
||||
r = prepare_reexecute(m, &arg_serialization, ret_fds, false);
|
||||
if (r < 0) {
|
||||
*ret_error_message = "Failed to prepare for reexecution";
|
||||
@@ -2005,6 +2011,10 @@ static int invoke_main_loop(
|
||||
return objective;
|
||||
|
||||
case MANAGER_SWITCH_ROOT:
|
||||
|
||||
manager_send_reloading(m); /* From the perspective of the manager calling us this is
|
||||
* pretty much the same as a reload */
|
||||
|
||||
manager_set_switching_root(m, true);
|
||||
|
||||
if (!m->switch_root_init) {
|
||||
|
||||
@@ -809,6 +809,8 @@ static int manager_find_credentials_dirs(Manager *m) {
|
||||
}
|
||||
|
||||
void manager_set_switching_root(Manager *m, bool switching_root) {
|
||||
assert(m);
|
||||
|
||||
m->switching_root = MANAGER_IS_SYSTEM(m) && switching_root;
|
||||
}
|
||||
|
||||
@@ -3646,6 +3648,18 @@ void manager_check_finished(Manager *m) {
|
||||
manager_invalidate_startup_units(m);
|
||||
}
|
||||
|
||||
void manager_send_reloading(Manager *m) {
|
||||
assert(m);
|
||||
|
||||
/* Let whoever invoked us know that we are now reloading */
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"RELOADING=1\n"
|
||||
"MONOTONIC_USEC=" USEC_FMT "\n", now(CLOCK_MONOTONIC));
|
||||
|
||||
/* And ensure that we'll send READY=1 again as soon as we are ready again */
|
||||
m->ready_sent = false;
|
||||
}
|
||||
|
||||
static bool generator_path_any(const char* const* paths) {
|
||||
bool found = false;
|
||||
|
||||
|
||||
@@ -538,6 +538,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u);
|
||||
bool manager_unit_inactive_or_pending(Manager *m, const char *name);
|
||||
|
||||
void manager_check_finished(Manager *m);
|
||||
void manager_send_reloading(Manager *m);
|
||||
|
||||
void disable_printk_ratelimit(void);
|
||||
void manager_recheck_dbus(Manager *m);
|
||||
|
||||
+159
-67
@@ -54,6 +54,8 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
|
||||
[SERVICE_RUNNING] = UNIT_ACTIVE,
|
||||
[SERVICE_EXITED] = UNIT_ACTIVE,
|
||||
[SERVICE_RELOAD] = UNIT_RELOADING,
|
||||
[SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING,
|
||||
[SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING,
|
||||
[SERVICE_STOP] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
|
||||
@@ -78,6 +80,8 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] =
|
||||
[SERVICE_RUNNING] = UNIT_ACTIVE,
|
||||
[SERVICE_EXITED] = UNIT_ACTIVE,
|
||||
[SERVICE_RELOAD] = UNIT_RELOADING,
|
||||
[SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING,
|
||||
[SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING,
|
||||
[SERVICE_STOP] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING,
|
||||
[SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
|
||||
@@ -124,6 +128,8 @@ static void service_init(Unit *u) {
|
||||
s->watchdog_original_usec = USEC_INFINITY;
|
||||
|
||||
s->oom_policy = _OOM_POLICY_INVALID;
|
||||
s->reload_begin_usec = USEC_INFINITY;
|
||||
s->reload_signal = SIGHUP;
|
||||
}
|
||||
|
||||
static void service_unwatch_control_pid(Service *s) {
|
||||
@@ -767,7 +773,7 @@ static int service_add_extras(Service *s) {
|
||||
|
||||
/* If the service needs the notify socket, let's enable it automatically. */
|
||||
if (s->notify_access == NOTIFY_NONE &&
|
||||
(s->type == SERVICE_NOTIFY || s->watchdog_usec > 0 || s->n_fd_store_max > 0))
|
||||
(IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) || s->watchdog_usec > 0 || s->n_fd_store_max > 0))
|
||||
s->notify_access = NOTIFY_MAIN;
|
||||
|
||||
/* If no OOM policy was explicitly set, then default to the configure default OOM policy. Except when
|
||||
@@ -832,7 +838,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
"%sRestart: %s\n"
|
||||
"%sNotifyAccess: %s\n"
|
||||
"%sNotifyState: %s\n"
|
||||
"%sOOMPolicy: %s\n",
|
||||
"%sOOMPolicy: %s\n"
|
||||
"%sReloadSignal: %s\n",
|
||||
prefix, service_state_to_string(s->state),
|
||||
prefix, service_result_to_string(s->result),
|
||||
prefix, service_result_to_string(s->reload_result),
|
||||
@@ -845,7 +852,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
prefix, service_restart_to_string(s->restart),
|
||||
prefix, notify_access_to_string(s->notify_access),
|
||||
prefix, notify_state_to_string(s->notify_state),
|
||||
prefix, oom_policy_to_string(s->oom_policy));
|
||||
prefix, oom_policy_to_string(s->oom_policy),
|
||||
prefix, signal_to_string(s->reload_signal));
|
||||
|
||||
if (s->control_pid > 0)
|
||||
fprintf(f,
|
||||
@@ -1105,7 +1113,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
if (!IN_SET(state,
|
||||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_AUTO_RESTART,
|
||||
@@ -1114,7 +1122,8 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
|
||||
if (!IN_SET(state,
|
||||
SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) {
|
||||
service_unwatch_main_pid(s);
|
||||
@@ -1123,7 +1132,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
|
||||
if (!IN_SET(state,
|
||||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_CLEANING)) {
|
||||
@@ -1139,7 +1148,8 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
|
||||
if (!IN_SET(state,
|
||||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) &&
|
||||
!(state == SERVICE_DEAD && UNIT(s)->job))
|
||||
@@ -1148,7 +1158,7 @@ static void service_set_state(Service *s, ServiceState state) {
|
||||
if (state != SERVICE_START)
|
||||
s->exec_fd_event_source = sd_event_source_disable_unref(s->exec_fd_event_source);
|
||||
|
||||
if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
|
||||
if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY))
|
||||
service_stop_watchdog(s);
|
||||
|
||||
/* For the inactive states unit_notify() will trim the cgroup,
|
||||
@@ -1174,6 +1184,8 @@ static usec_t service_coldplug_timeout(Service *s) {
|
||||
case SERVICE_START:
|
||||
case SERVICE_START_POST:
|
||||
case SERVICE_RELOAD:
|
||||
case SERVICE_RELOAD_SIGNAL:
|
||||
case SERVICE_RELOAD_NOTIFY:
|
||||
return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_start_usec);
|
||||
|
||||
case SERVICE_RUNNING:
|
||||
@@ -1220,7 +1232,8 @@ static int service_coldplug(Unit *u) {
|
||||
pid_is_unwaited(s->main_pid) &&
|
||||
(IN_SET(s->deserialized_state,
|
||||
SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RUNNING, SERVICE_RELOAD,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) {
|
||||
r = unit_watch_pid(UNIT(s), s->main_pid, false);
|
||||
@@ -1232,7 +1245,7 @@ static int service_coldplug(Unit *u) {
|
||||
pid_is_unwaited(s->control_pid) &&
|
||||
IN_SET(s->deserialized_state,
|
||||
SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST,
|
||||
SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
|
||||
SERVICE_CLEANING)) {
|
||||
@@ -1247,7 +1260,7 @@ static int service_coldplug(Unit *u) {
|
||||
(void) unit_setup_exec_runtime(u);
|
||||
}
|
||||
|
||||
if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD))
|
||||
if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY))
|
||||
service_start_watchdog(s);
|
||||
|
||||
if (UNIT_ISSET(s->accept_socket)) {
|
||||
@@ -2274,7 +2287,7 @@ static void service_enter_start(Service *s) {
|
||||
s->control_pid = pid;
|
||||
service_set_state(s, SERVICE_START);
|
||||
|
||||
} else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_EXEC)) {
|
||||
} else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD, SERVICE_EXEC)) {
|
||||
|
||||
/* For oneshot services we wait until the start process exited, too, but it is our main process. */
|
||||
|
||||
@@ -2418,7 +2431,7 @@ static void service_enter_reload_by_notify(Service *s) {
|
||||
assert(s);
|
||||
|
||||
service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
|
||||
service_set_state(s, SERVICE_RELOAD);
|
||||
service_set_state(s, SERVICE_RELOAD_NOTIFY);
|
||||
|
||||
/* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */
|
||||
r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error);
|
||||
@@ -2427,6 +2440,7 @@ static void service_enter_reload_by_notify(Service *s) {
|
||||
}
|
||||
|
||||
static void service_enter_reload(Service *s) {
|
||||
bool killed = false;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
@@ -2434,6 +2448,18 @@ static void service_enter_reload(Service *s) {
|
||||
service_unwatch_control_pid(s);
|
||||
s->reload_result = SERVICE_SUCCESS;
|
||||
|
||||
usec_t ts = now(CLOCK_MONOTONIC);
|
||||
|
||||
if (s->type == SERVICE_NOTIFY_RELOAD && s->main_pid > 0) {
|
||||
r = kill_and_sigcont(s->main_pid, s->reload_signal);
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to send reload signal: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
killed = true;
|
||||
}
|
||||
|
||||
s->control_command = s->exec_command[SERVICE_EXEC_RELOAD];
|
||||
if (s->control_command) {
|
||||
s->control_command_id = SERVICE_EXEC_RELOAD;
|
||||
@@ -2443,17 +2469,28 @@ static void service_enter_reload(Service *s) {
|
||||
s->timeout_start_usec,
|
||||
EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP,
|
||||
&s->control_pid);
|
||||
if (r < 0)
|
||||
if (r < 0) {
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
service_set_state(s, SERVICE_RELOAD);
|
||||
} else
|
||||
} else if (killed) {
|
||||
service_arm_timer(s, /* relative= */ true, s->timeout_start_usec);
|
||||
service_set_state(s, SERVICE_RELOAD_SIGNAL);
|
||||
} else {
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Store the timestamp when we started reloading: when reloading via SIGHUP we won't leave the reload
|
||||
* state until we received both RELOADING=1 and READY=1 with MONOTONIC_USEC= set to a value above
|
||||
* this. Thus we know for sure the reload cycle was executed *after* we requested it, and is not one
|
||||
* that was already in progress before. */
|
||||
s->reload_begin_usec = ts;
|
||||
return;
|
||||
|
||||
fail:
|
||||
log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m");
|
||||
s->reload_result = SERVICE_FAILURE_RESOURCES;
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
}
|
||||
@@ -2616,9 +2653,8 @@ static int service_stop(Unit *u) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If there's already something running we go directly into
|
||||
* kill mode. */
|
||||
if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP_WATCHDOG)) {
|
||||
/* If there's already something running we go directly into kill mode. */
|
||||
if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, SERVICE_STOP_WATCHDOG)) {
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS);
|
||||
return 0;
|
||||
}
|
||||
@@ -2651,7 +2687,8 @@ _pure_ static bool service_can_reload(Unit *u) {
|
||||
|
||||
assert(s);
|
||||
|
||||
return !!s->exec_command[SERVICE_EXEC_RELOAD];
|
||||
return s->exec_command[SERVICE_EXEC_RELOAD] ||
|
||||
s->type == SERVICE_NOTIFY_RELOAD;
|
||||
}
|
||||
|
||||
static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecCommand *current) {
|
||||
@@ -2827,6 +2864,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
if (s->watchdog_original_usec != USEC_INFINITY)
|
||||
(void) serialize_item_format(f, "watchdog-original-usec", USEC_FMT, s->watchdog_original_usec);
|
||||
|
||||
if (s->reload_begin_usec != USEC_INFINITY)
|
||||
(void) serialize_item_format(f, "reload-begin-usec", USEC_FMT, s->reload_begin_usec);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3165,6 +3205,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
|
||||
log_unit_debug_errno(u, r, "Failed to parse serialized flush restart counter setting '%s': %m", value);
|
||||
else
|
||||
s->flush_n_restarts = r;
|
||||
} else if (streq(key, "reload-begin-usec")) {
|
||||
r = deserialize_usec(value, &s->reload_begin_usec);
|
||||
if (r < 0)
|
||||
log_unit_debug_errno(u, r, "Failed to parse serialized reload begin timestamp '%s', ignoring: %m", value);
|
||||
} else
|
||||
log_unit_debug(u, "Unknown serialization key: %s", key);
|
||||
|
||||
@@ -3368,7 +3412,7 @@ static void service_notify_cgroup_empty_event(Unit *u) {
|
||||
* SIGCHLD for. */
|
||||
|
||||
case SERVICE_START:
|
||||
if (s->type == SERVICE_NOTIFY &&
|
||||
if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) &&
|
||||
main_pid_good(s) == 0 &&
|
||||
control_pid_good(s) == 0) {
|
||||
/* No chance of getting a ready notification anymore */
|
||||
@@ -3572,17 +3616,19 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
} else {
|
||||
s->main_command = NULL;
|
||||
|
||||
/* Services with ExitType=cgroup do not act on main PID exiting,
|
||||
* unless the cgroup is already empty */
|
||||
/* Services with ExitType=cgroup do not act on main PID exiting, unless the cgroup is
|
||||
* already empty */
|
||||
if (s->exit_type == SERVICE_EXIT_MAIN || cgroup_good(s) <= 0) {
|
||||
/* The service exited, so the service is officially gone. */
|
||||
switch (s->state) {
|
||||
|
||||
case SERVICE_START_POST:
|
||||
case SERVICE_RELOAD:
|
||||
/* If neither main nor control processes are running then
|
||||
* the current state can never exit cleanly, hence immediately
|
||||
* terminate the service. */
|
||||
case SERVICE_RELOAD_SIGNAL:
|
||||
case SERVICE_RELOAD_NOTIFY:
|
||||
/* If neither main nor control processes are running then the current
|
||||
* state can never exit cleanly, hence immediately terminate the
|
||||
* service. */
|
||||
if (control_pid_good(s) <= 0)
|
||||
service_enter_stop(s, f);
|
||||
|
||||
@@ -3601,7 +3647,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
else
|
||||
service_enter_signal(s, SERVICE_STOP_SIGTERM, f);
|
||||
break;
|
||||
} else if (s->type == SERVICE_NOTIFY) {
|
||||
} else if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD)) {
|
||||
/* Only enter running through a notification, so that the
|
||||
* SERVICE_START state signifies that no ready notification
|
||||
* has been received */
|
||||
@@ -3694,15 +3740,13 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
s->control_command->command_next &&
|
||||
f == SERVICE_SUCCESS) {
|
||||
|
||||
/* There is another command to *
|
||||
* execute, so let's do that. */
|
||||
/* There is another command to * execute, so let's do that. */
|
||||
|
||||
log_unit_debug(u, "Running next control command for state %s.", service_state_to_string(s->state));
|
||||
service_run_next_control(s);
|
||||
|
||||
} else {
|
||||
/* No further commands for this step, so let's
|
||||
* figure out what to do next */
|
||||
/* No further commands for this step, so let's figure out what to do next */
|
||||
|
||||
s->control_command = NULL;
|
||||
s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID;
|
||||
@@ -3780,12 +3824,22 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
|
||||
break;
|
||||
|
||||
case SERVICE_RELOAD:
|
||||
case SERVICE_RELOAD_SIGNAL:
|
||||
case SERVICE_RELOAD_NOTIFY:
|
||||
if (f == SERVICE_SUCCESS)
|
||||
if (service_load_pid_file(s, true) < 0)
|
||||
service_search_main_pid(s);
|
||||
|
||||
s->reload_result = f;
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
|
||||
/* If the last notification we received from the service process indiciates
|
||||
* we are still reloading, then don't leave reloading state just yet, just
|
||||
* transition into SERVICE_RELOAD_NOTIFY, to wait for the READY=1 coming,
|
||||
* too. */
|
||||
if (s->notify_state == NOTIFY_RELOADING)
|
||||
service_set_state(s, SERVICE_RELOAD_NOTIFY);
|
||||
else
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
break;
|
||||
|
||||
case SERVICE_STOP:
|
||||
@@ -3888,6 +3942,8 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us
|
||||
break;
|
||||
|
||||
case SERVICE_RELOAD:
|
||||
case SERVICE_RELOAD_SIGNAL:
|
||||
case SERVICE_RELOAD_NOTIFY:
|
||||
log_unit_warning(UNIT(s), "Reload operation timed out. Killing reload process.");
|
||||
service_kill_control_process(s);
|
||||
s->reload_result = SERVICE_FAILURE_TIMEOUT;
|
||||
@@ -4113,6 +4169,7 @@ static void service_notify_message(
|
||||
|
||||
Service *s = SERVICE(u);
|
||||
bool notify_dbus = false;
|
||||
usec_t monotonic_usec = USEC_INFINITY;
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
@@ -4131,7 +4188,7 @@ static void service_notify_message(
|
||||
|
||||
/* Interpret MAINPID= */
|
||||
e = strv_find_startswith(tags, "MAINPID=");
|
||||
if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) {
|
||||
if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY)) {
|
||||
pid_t new_main_pid;
|
||||
|
||||
if (parse_pid(e, &new_main_pid) < 0)
|
||||
@@ -4160,43 +4217,73 @@ static void service_notify_message(
|
||||
}
|
||||
}
|
||||
|
||||
/* Interpret READY=/STOPPING=/RELOADING=. Last one wins. */
|
||||
STRV_FOREACH_BACKWARDS(i, tags) {
|
||||
/* Parse MONOTONIC_USEC= */
|
||||
e = strv_find_startswith(tags, "MONOTONIC_USEC=");
|
||||
if (e) {
|
||||
r = safe_atou64(e, &monotonic_usec);
|
||||
if (r < 0)
|
||||
log_unit_warning_errno(u, r, "Failed to parse MONOTONIC_USEC= field in notification message, ignoring: %s", e);
|
||||
}
|
||||
|
||||
if (streq(*i, "READY=1")) {
|
||||
s->notify_state = NOTIFY_READY;
|
||||
/* Interpret READY=/STOPPING=/RELOADING=. STOPPING= wins over the others, and READY= over RELOADING= */
|
||||
if (strv_contains(tags, "STOPPING=1")) {
|
||||
s->notify_state = NOTIFY_STOPPING;
|
||||
|
||||
/* Type=notify services inform us about completed
|
||||
* initialization with READY=1 */
|
||||
if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START)
|
||||
service_enter_start_post(s);
|
||||
if (IN_SET(s->state, SERVICE_RUNNING, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY))
|
||||
service_enter_stop_by_notify(s);
|
||||
|
||||
/* Sending READY=1 while we are reloading informs us
|
||||
* that the reloading is complete */
|
||||
if (s->state == SERVICE_RELOAD && s->control_pid == 0)
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
notify_dbus = true;
|
||||
|
||||
notify_dbus = true;
|
||||
break;
|
||||
} else if (strv_contains(tags, "READY=1")) {
|
||||
|
||||
} else if (streq(*i, "RELOADING=1")) {
|
||||
s->notify_state = NOTIFY_RELOADING;
|
||||
s->notify_state = NOTIFY_READY;
|
||||
|
||||
if (s->state == SERVICE_RUNNING)
|
||||
service_enter_reload_by_notify(s);
|
||||
/* Type=notify services inform us about completed initialization with READY=1 */
|
||||
if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) &&
|
||||
s->state == SERVICE_START)
|
||||
service_enter_start_post(s);
|
||||
|
||||
notify_dbus = true;
|
||||
break;
|
||||
/* Sending READY=1 while we are reloading informs us that the reloading is complete. */
|
||||
if (s->state == SERVICE_RELOAD_NOTIFY)
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
|
||||
} else if (streq(*i, "STOPPING=1")) {
|
||||
s->notify_state = NOTIFY_STOPPING;
|
||||
/* Combined RELOADING=1 and READY=1? Then this is indication that the service started and
|
||||
* immediately finished reloading. */
|
||||
if (s->state == SERVICE_RELOAD_SIGNAL &&
|
||||
strv_contains(tags, "RELOADING=1") &&
|
||||
monotonic_usec != USEC_INFINITY &&
|
||||
monotonic_usec >= s->reload_begin_usec) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
|
||||
if (s->state == SERVICE_RUNNING)
|
||||
service_enter_stop_by_notify(s);
|
||||
/* Propagate a reload explicitly */
|
||||
r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error);
|
||||
if (r < 0)
|
||||
log_unit_warning(UNIT(s), "Failed to schedule propagation of reload, ignoring: %s", bus_error_message(&error, r));
|
||||
|
||||
notify_dbus = true;
|
||||
break;
|
||||
service_enter_running(s, SERVICE_SUCCESS);
|
||||
}
|
||||
|
||||
notify_dbus = true;
|
||||
|
||||
} else if (strv_contains(tags, "RELOADING=1")) {
|
||||
|
||||
s->notify_state = NOTIFY_RELOADING;
|
||||
|
||||
/* Sending RELOADING=1 after we send SIGHUP to request a reload will transition
|
||||
* things to "reload-notify" state, where we'll wait for READY=1 to let us know the
|
||||
* reload is done. Note that we insist on a timestamp being sent along here, so that
|
||||
* we know for sure this is a reload cycle initiated *after* we sent the signal */
|
||||
if (s->state == SERVICE_RELOAD_SIGNAL &&
|
||||
monotonic_usec != USEC_INFINITY &&
|
||||
monotonic_usec >= s->reload_begin_usec)
|
||||
/* Note, we don't call service_enter_reload_by_notify() here, because we
|
||||
* don't need reload propagation nor do we want to restart the time-out. */
|
||||
service_set_state(s, SERVICE_RELOAD_NOTIFY);
|
||||
|
||||
if (s->state == SERVICE_RUNNING)
|
||||
service_enter_reload_by_notify(s);
|
||||
|
||||
notify_dbus = true;
|
||||
}
|
||||
|
||||
/* Interpret STATUS= */
|
||||
@@ -4326,7 +4413,9 @@ static bool pick_up_pid_from_bus_name(Service *s) {
|
||||
SERVICE_START,
|
||||
SERVICE_START_POST,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD);
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_RELOAD_SIGNAL,
|
||||
SERVICE_RELOAD_NOTIFY);
|
||||
}
|
||||
|
||||
static int bus_name_pid_lookup_callback(sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) {
|
||||
@@ -4533,6 +4622,8 @@ static bool service_needs_console(Unit *u) {
|
||||
SERVICE_START_POST,
|
||||
SERVICE_RUNNING,
|
||||
SERVICE_RELOAD,
|
||||
SERVICE_RELOAD_SIGNAL,
|
||||
SERVICE_RELOAD_NOTIFY,
|
||||
SERVICE_STOP,
|
||||
SERVICE_STOP_WATCHDOG,
|
||||
SERVICE_STOP_SIGTERM,
|
||||
@@ -4655,13 +4746,14 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart);
|
||||
|
||||
static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
|
||||
[SERVICE_SIMPLE] = "simple",
|
||||
[SERVICE_FORKING] = "forking",
|
||||
[SERVICE_ONESHOT] = "oneshot",
|
||||
[SERVICE_DBUS] = "dbus",
|
||||
[SERVICE_NOTIFY] = "notify",
|
||||
[SERVICE_IDLE] = "idle",
|
||||
[SERVICE_EXEC] = "exec",
|
||||
[SERVICE_SIMPLE] = "simple",
|
||||
[SERVICE_FORKING] = "forking",
|
||||
[SERVICE_ONESHOT] = "oneshot",
|
||||
[SERVICE_DBUS] = "dbus",
|
||||
[SERVICE_NOTIFY] = "notify",
|
||||
[SERVICE_NOTIFY_RELOAD] = "notify-reload",
|
||||
[SERVICE_IDLE] = "idle",
|
||||
[SERVICE_EXEC] = "exec",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
|
||||
|
||||
+11
-7
@@ -25,13 +25,14 @@ typedef enum ServiceRestart {
|
||||
} ServiceRestart;
|
||||
|
||||
typedef enum ServiceType {
|
||||
SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */
|
||||
SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */
|
||||
SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */
|
||||
SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */
|
||||
SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */
|
||||
SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */
|
||||
SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */
|
||||
SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */
|
||||
SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */
|
||||
SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */
|
||||
SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */
|
||||
SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */
|
||||
SERVICE_NOTIFY_RELOAD, /* just like SERVICE_NOTIFY, but also implements a reload protocol via SIGHUP */
|
||||
SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */
|
||||
SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */
|
||||
_SERVICE_TYPE_MAX,
|
||||
_SERVICE_TYPE_INVALID = -EINVAL,
|
||||
} ServiceType;
|
||||
@@ -218,6 +219,9 @@ struct Service {
|
||||
OOMPolicy oom_policy;
|
||||
|
||||
LIST_HEAD(OpenFile, open_files);
|
||||
|
||||
int reload_signal;
|
||||
usec_t reload_begin_usec;
|
||||
};
|
||||
|
||||
static inline usec_t service_timeout_abort_usec(Service *s) {
|
||||
|
||||
@@ -1020,6 +1020,11 @@ static int manager_dispatch_reload_signal(sd_event_source *s, const struct signa
|
||||
Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"RELOADING=1\n"
|
||||
"STATUS=Reloading configuration...\n"
|
||||
"MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC));
|
||||
|
||||
manager_reset_config(m);
|
||||
r = manager_parse_config_file(m);
|
||||
if (r < 0)
|
||||
@@ -1027,6 +1032,7 @@ static int manager_dispatch_reload_signal(sd_event_source *s, const struct signa
|
||||
else
|
||||
log_info("Config file reloaded.");
|
||||
|
||||
(void) sd_notify(/* unset= */ false, NOTIFY_READY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,6 @@ static int bus_method_reconfigure_link(sd_bus_message *message, void *userdata,
|
||||
|
||||
static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *manager = userdata;
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
r = bus_verify_polkit_async(message, CAP_NET_ADMIN,
|
||||
@@ -209,20 +208,10 @@ static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_err
|
||||
if (r == 0)
|
||||
return 1; /* Polkit will call us back */
|
||||
|
||||
r = netdev_load(manager, true);
|
||||
r = manager_reload(manager);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = network_reload(manager);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
HASHMAP_FOREACH(link, manager->links_by_index) {
|
||||
r = link_reconfigure(link, /* force = */ false);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sd_bus_reply_method_return(message, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -474,6 +474,14 @@ static int signal_restart_callback(sd_event_source *s, const struct signalfd_sig
|
||||
return sd_event_exit(sd_event_source_get_event(s), 0);
|
||||
}
|
||||
|
||||
static int signal_reload_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
|
||||
manager_reload(m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int manager_set_keep_configuration(Manager *m) {
|
||||
int r;
|
||||
|
||||
@@ -508,12 +516,11 @@ int manager_setup(Manager *m) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0);
|
||||
|
||||
(void) sd_event_set_watchdog(m->event, true);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, signal_terminate_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, signal_terminate_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGUSR2 | SD_EVENT_SIGNAL_PROCMASK, signal_restart_callback, m);
|
||||
(void) sd_event_add_signal(m->event, NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, signal_reload_callback, m);
|
||||
|
||||
r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m);
|
||||
if (r < 0)
|
||||
@@ -1069,3 +1076,34 @@ int manager_set_timezone(Manager *m, const char *tz) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_reload(Manager *m) {
|
||||
Link *link;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"RELOADING=1\n"
|
||||
"STATUS=Reloading configuration...\n"
|
||||
"MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC));
|
||||
|
||||
r = netdev_load(m, /* reload= */ true);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = network_reload(m);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
HASHMAP_FOREACH(link, m->links_by_index) {
|
||||
r = link_reconfigure(link, /* force = */ false);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
finish:
|
||||
(void) sd_notify(/* unset= */ false, NOTIFY_READY);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -115,4 +115,6 @@ int manager_enumerate(Manager *m);
|
||||
int manager_set_hostname(Manager *m, const char *hostname);
|
||||
int manager_set_timezone(Manager *m, const char *timezone);
|
||||
|
||||
int manager_reload(Manager *m);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
|
||||
|
||||
@@ -81,8 +81,6 @@ static int run(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Could not create runtime directory 'lldp': %m");
|
||||
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
|
||||
|
||||
r = manager_new(&m, /* test_mode = */ false);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Could not create manager: %m");
|
||||
|
||||
+35
-4
@@ -23,6 +23,8 @@
|
||||
#include "user-util.h"
|
||||
|
||||
static bool arg_ready = false;
|
||||
static bool arg_reloading = false;
|
||||
static bool arg_stopping = false;
|
||||
static pid_t arg_pid = 0;
|
||||
static const char *arg_status = NULL;
|
||||
static bool arg_booted = false;
|
||||
@@ -42,7 +44,10 @@ static int help(void) {
|
||||
"\n%sNotify the init system about service status updates.%s\n\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
" --ready Inform the init system about service start-up completion\n"
|
||||
" --ready Inform the service manager about service start-up/reload\n"
|
||||
" completion\n"
|
||||
" --reloading Inform the service manager about configuration reloading\n"
|
||||
" --stopping Inform the service manager about service shutdown\n"
|
||||
" --pid[=PID] Set main PID of daemon\n"
|
||||
" --uid=USER Set user to send from\n"
|
||||
" --status=TEXT Set status text\n"
|
||||
@@ -81,6 +86,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
enum {
|
||||
ARG_READY = 0x100,
|
||||
ARG_RELOADING,
|
||||
ARG_STOPPING,
|
||||
ARG_VERSION,
|
||||
ARG_PID,
|
||||
ARG_STATUS,
|
||||
@@ -93,6 +100,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "ready", no_argument, NULL, ARG_READY },
|
||||
{ "reloading", no_argument, NULL, ARG_RELOADING },
|
||||
{ "stopping", no_argument, NULL, ARG_STOPPING },
|
||||
{ "pid", optional_argument, NULL, ARG_PID },
|
||||
{ "status", required_argument, NULL, ARG_STATUS },
|
||||
{ "booted", no_argument, NULL, ARG_BOOTED },
|
||||
@@ -120,6 +129,14 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_ready = true;
|
||||
break;
|
||||
|
||||
case ARG_RELOADING:
|
||||
arg_reloading = true;
|
||||
break;
|
||||
|
||||
case ARG_STOPPING:
|
||||
arg_stopping = true;
|
||||
break;
|
||||
|
||||
case ARG_PID:
|
||||
if (isempty(optarg) || streq(optarg, "auto")) {
|
||||
arg_pid = getppid();
|
||||
@@ -176,6 +193,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
if (optind >= argc &&
|
||||
!arg_ready &&
|
||||
!arg_stopping &&
|
||||
!arg_reloading &&
|
||||
!arg_status &&
|
||||
!arg_pid &&
|
||||
!arg_booted) {
|
||||
@@ -187,10 +206,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
static int run(int argc, char* argv[]) {
|
||||
_cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL;
|
||||
_cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL, *monotonic_usec = NULL;
|
||||
_cleanup_strv_free_ char **final_env = NULL;
|
||||
char* our_env[4];
|
||||
unsigned i = 0;
|
||||
char* our_env[7];
|
||||
size_t i = 0;
|
||||
pid_t source_pid;
|
||||
int r;
|
||||
|
||||
@@ -212,9 +231,21 @@ static int run(int argc, char* argv[]) {
|
||||
return r <= 0;
|
||||
}
|
||||
|
||||
if (arg_reloading) {
|
||||
our_env[i++] = (char*) "RELOADING=1";
|
||||
|
||||
if (asprintf(&monotonic_usec, "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)) < 0)
|
||||
return log_oom();
|
||||
|
||||
our_env[i++] = monotonic_usec;
|
||||
}
|
||||
|
||||
if (arg_ready)
|
||||
our_env[i++] = (char*) "READY=1";
|
||||
|
||||
if (arg_stopping)
|
||||
our_env[i++] = (char*) "STOPPING=1";
|
||||
|
||||
if (arg_status) {
|
||||
status = strjoin("STATUS=", arg_status);
|
||||
if (!status)
|
||||
|
||||
@@ -2094,7 +2094,8 @@ static int bus_append_kill_property(sd_bus_message *m, const char *field, const
|
||||
if (STR_IN_SET(field, "KillSignal",
|
||||
"RestartKillSignal",
|
||||
"FinalKillSignal",
|
||||
"WatchdogSignal"))
|
||||
"WatchdogSignal",
|
||||
"ReloadSignal"))
|
||||
return bus_append_signal_from_string(m, field, eq);
|
||||
|
||||
return 0;
|
||||
|
||||
+27
-20
@@ -32,6 +32,7 @@
|
||||
#include "cgroup-setup.h"
|
||||
#include "cgroup-util.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "daemon-util.h"
|
||||
#include "dev-setup.h"
|
||||
#include "device-monitor-private.h"
|
||||
#include "device-private.h"
|
||||
@@ -330,9 +331,7 @@ static void manager_exit(Manager *manager) {
|
||||
|
||||
manager->exit = true;
|
||||
|
||||
sd_notify(false,
|
||||
"STOPPING=1\n"
|
||||
"STATUS=Starting shutdown...");
|
||||
(void) sd_notify(/* unset= */ false, NOTIFY_STOPPING);
|
||||
|
||||
/* close sources of new events and discard buffered events */
|
||||
manager->ctrl = udev_ctrl_unref(manager->ctrl);
|
||||
@@ -350,7 +349,7 @@ static void manager_exit(Manager *manager) {
|
||||
static void notify_ready(void) {
|
||||
int r;
|
||||
|
||||
r = sd_notifyf(false,
|
||||
r = sd_notifyf(/* unset= */ false,
|
||||
"READY=1\n"
|
||||
"STATUS=Processing with %u children at max", arg_children_max);
|
||||
if (r < 0)
|
||||
@@ -375,23 +374,33 @@ static void manager_reload(Manager *manager, bool force) {
|
||||
mac_selinux_maybe_reload();
|
||||
|
||||
/* Nothing changed. It is not necessary to reload. */
|
||||
if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload())
|
||||
return;
|
||||
if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload()) {
|
||||
|
||||
sd_notify(false,
|
||||
"RELOADING=1\n"
|
||||
"STATUS=Flushing configuration...");
|
||||
if (!force)
|
||||
return;
|
||||
|
||||
manager_kill_workers(manager, false);
|
||||
/* If we eat this up, then tell our service manager to just continue */
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"RELOADING=1\n"
|
||||
"STATUS=Skipping configuration reloading, nothing changed.\n"
|
||||
"MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC));
|
||||
} else {
|
||||
(void) sd_notifyf(/* unset= */ false,
|
||||
"RELOADING=1\n"
|
||||
"STATUS=Flushing configuration...\n"
|
||||
"MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC));
|
||||
|
||||
udev_builtin_exit();
|
||||
udev_builtin_init();
|
||||
manager_kill_workers(manager, false);
|
||||
|
||||
r = udev_rules_load(&rules, arg_resolve_name_timing);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
|
||||
else
|
||||
udev_rules_free_and_replace(manager->rules, rules);
|
||||
udev_builtin_exit();
|
||||
udev_builtin_init();
|
||||
|
||||
r = udev_rules_load(&rules, arg_resolve_name_timing);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m");
|
||||
else
|
||||
udev_rules_free_and_replace(manager->rules, rules);
|
||||
}
|
||||
|
||||
notify_ready();
|
||||
}
|
||||
@@ -1985,9 +1994,7 @@ static int main_loop(Manager *manager) {
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Event loop failed: %m");
|
||||
|
||||
sd_notify(false,
|
||||
"STOPPING=1\n"
|
||||
"STATUS=Shutting down...");
|
||||
(void) sd_notify(/* unset= */ false, NOTIFY_STOPPING);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,6 +104,59 @@ sleep 10
|
||||
|
||||
systemctl daemon-reload
|
||||
|
||||
# Let's now test the notify-reload logic
|
||||
|
||||
cat >/run/notify-reload-test.sh <<EOF
|
||||
#!/usr/bin/env bash
|
||||
set -eux
|
||||
set -o pipefail
|
||||
|
||||
EXIT_STATUS=88
|
||||
LEAVE=0
|
||||
|
||||
function reload() {
|
||||
systemd-notify --reloading --status="Adding 11 to exit status"
|
||||
EXIT_STATUS=\$((\$EXIT_STATUS + 11))
|
||||
systemd-notify --ready --status="Back running"
|
||||
}
|
||||
|
||||
function leave() {
|
||||
systemd-notify --stopping --status="Adding 7 to exit status"
|
||||
EXIT_STATUS=\$((\$EXIT_STATUS + 7))
|
||||
LEAVE=1
|
||||
return 0
|
||||
}
|
||||
|
||||
trap reload SIGHUP
|
||||
trap leave SIGTERM
|
||||
|
||||
systemd-notify --ready
|
||||
systemd-notify --status="Running now"
|
||||
|
||||
while [ \$LEAVE = 0 ] ; do
|
||||
sleep 1
|
||||
done
|
||||
|
||||
systemd-notify --status="Adding 3 to exit status"
|
||||
EXIT_STATUS=\$((\$EXIT_STATUS + 3))
|
||||
exit \$EXIT_STATUS
|
||||
EOF
|
||||
|
||||
chmod +x /run/notify-reload-test.sh
|
||||
|
||||
systemd-analyze log-level debug
|
||||
|
||||
systemd-run --unit notify-reload-test -p Type=notify-reload -p KillMode=process /run/notify-reload-test.sh
|
||||
systemctl reload notify-reload-test
|
||||
systemctl stop notify-reload-test
|
||||
|
||||
test "$(systemctl show -p ExecMainStatus --value notify-reload-test)" = 109
|
||||
|
||||
systemctl reset-failed notify-reload-test
|
||||
rm /run/notify-reload-test.sh
|
||||
|
||||
systemd-analyze log-level info
|
||||
|
||||
echo OK >/testok
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -58,6 +58,7 @@ StateDirectory=systemd/linger
|
||||
SystemCallArchitectures=native
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallFilter=@system-service
|
||||
Type=notify-reload
|
||||
{{SERVICE_WATCHDOG}}
|
||||
|
||||
# Increase the default a bit in order to allow many simultaneous logins since
|
||||
|
||||
@@ -24,7 +24,6 @@ BusName=org.freedesktop.network1
|
||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW
|
||||
DeviceAllow=char-* rw
|
||||
ExecStart=!!{{ROOTLIBEXECDIR}}/systemd-networkd
|
||||
ExecReload=networkctl reload
|
||||
FileDescriptorStoreMax=512
|
||||
LockPersonality=yes
|
||||
MemoryDenyWriteExecute=yes
|
||||
@@ -48,7 +47,7 @@ RuntimeDirectoryPreserve=yes
|
||||
SystemCallArchitectures=native
|
||||
SystemCallErrorNumber=EPERM
|
||||
SystemCallFilter=@system-service
|
||||
Type=notify
|
||||
Type=notify-reload
|
||||
User=systemd-network
|
||||
{{SERVICE_WATCHDOG}}
|
||||
|
||||
|
||||
@@ -18,14 +18,13 @@ ConditionPathIsReadWrite=/sys
|
||||
[Service]
|
||||
CapabilityBoundingSet=~CAP_SYS_TIME CAP_WAKE_ALARM
|
||||
Delegate=pids
|
||||
Type=notify
|
||||
Type=notify-reload
|
||||
# Note that udev will reset the value internally for its workers
|
||||
OOMScoreAdjust=-1000
|
||||
Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket
|
||||
Restart=always
|
||||
RestartSec=0
|
||||
ExecStart={{ROOTLIBEXECDIR}}/systemd-udevd
|
||||
ExecReload=udevadm control --reload --timeout 0
|
||||
KillMode=mixed
|
||||
TasksMax=infinity
|
||||
PrivateMounts=yes
|
||||
|
||||
@@ -17,7 +17,7 @@ IgnoreOnIsolate=yes
|
||||
[Service]
|
||||
User=%i
|
||||
PAMName=systemd-user
|
||||
Type=notify
|
||||
Type=notify-reload
|
||||
ExecStart={{ROOTLIBEXECDIR}}/systemd --user
|
||||
Slice=user-%i.slice
|
||||
KillMode=mixed
|
||||
|
||||
Reference in New Issue
Block a user