Skip to content

Commit 5ec7a99

Browse files
committed
man: sd_notify() race is gone with sd_notify_barrier()
Add note for change of behaviour in systemd-notify, where parent pid trick is only used when --no-block is passed, and with enough privileges ofcourse. Also, fix a small error in systemd(1).
1 parent 4f07ddf commit 5ec7a99

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

man/systemd-notify.xml

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,19 @@
5454
off the process, i.e. on all processes that match <varname>NotifyAccess=</varname><option>main</option> or
5555
<varname>NotifyAccess=</varname><option>exec</option>. Conversely, if an auxiliary process of the unit sends an
5656
<function>sd_notify()</function> message and immediately exits, the service manager might not be able to properly
57-
attribute the message to the unit, and thus will ignore it, even if
58-
<varname>NotifyAccess=</varname><option>all</option> is set for it.</para>
59-
60-
<para><command>systemd-notify</command> will first attempt to invoke <function>sd_notify()</function> pretending to
61-
have the PID of the invoking process. This will only succeed when invoked with sufficient privileges. On failure,
62-
it will then fall back to invoking it under its own PID. This behaviour is useful in order that when the tool is
63-
invoked from a shell script the shell process — and not the <command>systemd-notify</command> process — appears as
64-
sender of the message, which in turn is helpful if the shell process is the main process of a service, due to the
65-
limitations of <varname>NotifyAccess=</varname><option>all</option> described above.</para>
57+
attribute the message to the unit, and thus will ignore it, even if <varname>NotifyAccess=</varname><option>all
58+
</option> is set for it. When <option>--no-block</option> is used, all synchronization for reception of notifications
59+
is disabled, and hence the aforementioned race may occur if the invoking process is not the service manager or spawned
60+
by the service manager.</para>
61+
62+
<para>Hence, <command>systemd-notify</command> will first attempt to invoke <function>sd_notify()</function>
63+
pretending to have the PID of the invoking process. This will only succeed when invoked with sufficient privileges.
64+
On failure, it will then fall back to invoking it under its own PID. This behaviour is useful in order that when
65+
the tool is invoked from a shell script the shell process — and not the <command>systemd-notify</command> process
66+
— appears as sender of the message, which in turn is helpful if the shell process is the main process of a service,
67+
due to the limitations of <varname>NotifyAccess=</varname><option>all</option>. Use the <option>--pid=</option>
68+
switch to tweak this behaviour.</para>
69+
6670
</refsect1>
6771

6872
<refsect1>
@@ -129,6 +133,17 @@
129133
with systemd. </para></listitem>
130134
</varlistentry>
131135

136+
<varlistentry>
137+
<term><option>--no-block</option></term>
138+
139+
<listitem><para>Do not synchronously wait for the requested operation to finish.
140+
Use of this option is only recommended when <command>systemd-notify</command>
141+
is spawned by the service manager, or when the invoking process is directly spawned
142+
by the service manager and has enough privileges to allow <command>systemd-notify
143+
</command> to send the notification on its behalf. Sending notifications with
144+
this option set is prone to race conditions in all other cases.</para></listitem>
145+
</varlistentry>
146+
132147
<xi:include href="standard-options.xml" xpointer="help" />
133148
<xi:include href="standard-options.xml" xpointer="version" />
134149
</variablelist>

man/systemd.service.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,14 @@
959959
<option>exec</option>. Conversely, if an auxiliary process of the unit sends an
960960
<function>sd_notify()</function> message and immediately exits, the service manager might not be able to
961961
properly attribute the message to the unit, and thus will ignore it, even if
962-
<varname>NotifyAccess=</varname><option>all</option> is set for it.</para></listitem>
962+
<varname>NotifyAccess=</varname><option>all</option> is set for it.</para>
963+
964+
<para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of notifications
965+
to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as a synchronization point
966+
and ensures all notifications sent before this call have been picked up by the service manager when it returns
967+
successfully. Use of <function>sd_notify_barrier()</function> is needed for clients which are not invoked by the
968+
service manager, otherwise this synchronization mechanism is unnecessary for attribution of notifications to the
969+
unit.</para></listitem>
963970
</varlistentry>
964971

965972
<varlistentry>

man/systemd.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@
257257
execution compared to the target unit's state and is marked successful and
258258
complete when both satisfy. However, this job also pulls in other
259259
dependencies due to the defined relationships and thus leads to, in our
260-
our example, start jobs for any of those inactive units getting queued as
260+
example, start jobs for any of those inactive units getting queued as
261261
well.</para>
262262

263263
<para>systemd contains native implementations of various tasks

0 commit comments

Comments
 (0)