1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-04 21:47:31 +03:00

sd-daemon: add sd_pid_notifyf_with_fds()

I guess it was only a question of time until we need to add the final
frontier of notification functions: one that combines the features of
all the others:

1. specifiying a source PID
2. taking a list of fds to send along
3. accepting a format string for the status string

Hence, let's add it.
This commit is contained in:
Lennart Poettering 2023-04-14 17:48:47 +02:00
parent 4a75704b16
commit 4054d76151
5 changed files with 60 additions and 7 deletions

View File

@ -808,7 +808,8 @@ manpages = [
'sd_notifyf', 'sd_notifyf',
'sd_pid_notify', 'sd_pid_notify',
'sd_pid_notify_with_fds', 'sd_pid_notify_with_fds',
'sd_pid_notifyf'], 'sd_pid_notifyf',
'sd_pid_notifyf_with_fds'],
''], ''],
['sd_path_lookup', '3', ['sd_path_lookup_strv'], ''], ['sd_path_lookup', '3', ['sd_path_lookup_strv'], ''],
['sd_pid_get_owner_uid', ['sd_pid_get_owner_uid',

View File

@ -22,6 +22,7 @@
<refname>sd_pid_notify</refname> <refname>sd_pid_notify</refname>
<refname>sd_pid_notifyf</refname> <refname>sd_pid_notifyf</refname>
<refname>sd_pid_notify_with_fds</refname> <refname>sd_pid_notify_with_fds</refname>
<refname>sd_pid_notifyf_with_fds</refname>
<refname>sd_notify_barrier</refname> <refname>sd_notify_barrier</refname>
<refpurpose>Notify service manager about start-up completion and other service status changes</refpurpose> <refpurpose>Notify service manager about start-up completion and other service status changes</refpurpose>
</refnamediv> </refnamediv>
@ -67,6 +68,16 @@
<paramdef>unsigned <parameter>n_fds</parameter></paramdef> <paramdef>unsigned <parameter>n_fds</parameter></paramdef>
</funcprototype> </funcprototype>
<funcprototype>
<funcdef>int <function>sd_pid_notifyf_with_fds</function></funcdef>
<paramdef>pid_t <parameter>pid</parameter></paramdef>
<paramdef>int <parameter>unset_environment</parameter></paramdef>
<paramdef>const int *<parameter>fds</parameter></paramdef>
<paramdef>size_t <parameter>n_fds</parameter></paramdef>
<paramdef>const char *<parameter>format</parameter></paramdef>
<paramdef></paramdef>
</funcprototype>
<funcprototype> <funcprototype>
<funcdef>int <function>sd_notify_barrier</function></funcdef> <funcdef>int <function>sd_notify_barrier</function></funcdef>
<paramdef>int <parameter>unset_environment</parameter></paramdef> <paramdef>int <parameter>unset_environment</parameter></paramdef>
@ -326,12 +337,12 @@
able to properly attribute the message to the unit, and thus will ignore it, even if able to properly attribute the message to the unit, and thus will ignore it, even if
<varname>NotifyAccess=</varname><option>all</option> is set for it.</para> <varname>NotifyAccess=</varname><option>all</option> is set for it.</para>
<para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of notifications <para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of
to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as a synchronization point notifications to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as
and ensures all notifications sent before this call have been picked up by the service manager when it returns a synchronization point and ensures all notifications sent before this call have been picked up by the
successfully. Use of <function>sd_notify_barrier()</function> is needed for clients which are not invoked by the service manager when it returns successfully. Use of <function>sd_notify_barrier()</function> is needed
service manager, otherwise this synchronization mechanism is unnecessary for attribution of notifications to the for clients which are not invoked by the service manager, otherwise this synchronization mechanism is
unit.</para> unnecessary for attribution of notifications to the unit.</para>
<para><function>sd_notifyf()</function> is similar to <function>sd_notify()</function> but takes a <para><function>sd_notifyf()</function> is similar to <function>sd_notify()</function> but takes a
<function>printf()</function>-like format string plus arguments.</para> <function>printf()</function>-like format string plus arguments.</para>
@ -352,6 +363,11 @@
that file descriptors sent to the service manager on a message without <literal>FDSTORE=1</literal> are that file descriptors sent to the service manager on a message without <literal>FDSTORE=1</literal> are
immediately closed on reception.</para> immediately closed on reception.</para>
<para><function>sd_pid_notifyf_with_fds()</function> is a combination of
<function>sd_pid_notify_with_fds()</function> and <function>sd_notifyf()</function>, i.e. it accepts both
a PID and a set of file descriptors as input, and processes a format string to generate the state
string.</para>
<para><function>sd_notify_barrier()</function> allows the caller to synchronize against reception of <para><function>sd_notify_barrier()</function> allows the caller to synchronize against reception of
previously sent notification messages and uses the <varname>BARRIER=1</varname> command. It takes a previously sent notification messages and uses the <varname>BARRIER=1</varname> command. It takes a
relative <varname>timeout</varname> value in microseconds which is passed to relative <varname>timeout</varname> value in microseconds which is passed to

View File

@ -818,4 +818,5 @@ global:
sd_session_get_username; sd_session_get_username;
sd_session_get_start_time; sd_session_get_start_time;
sd_uid_get_login_time; sd_uid_get_login_time;
sd_pid_notifyf_with_fds;
} LIBSYSTEMD_253; } LIBSYSTEMD_253;

View File

@ -667,6 +667,36 @@ _public_ int sd_notifyf(int unset_environment, const char *format, ...) {
return sd_pid_notify(0, unset_environment, p); return sd_pid_notify(0, unset_environment, p);
} }
int sd_pid_notifyf_with_fds(
pid_t pid,
int unset_environment,
const int *fds, size_t n_fds,
const char *format, ...) {
_cleanup_free_ char *p = NULL;
int r;
/* Paranoia check: we traditionally used 'unsigned' as array size, but we nowadays more correctly use
* 'size_t'. sd_pid_notifyf_with_fds() and sd_pid_notify_with_fds() are from different eras, hence
* differ in this. Let's catch resulting incompatibilites early, even though they are pretty much
* theoretic only */
if (n_fds > UINT_MAX)
return -E2BIG;
if (format) {
va_list ap;
va_start(ap, format);
r = vasprintf(&p, format, ap);
va_end(ap);
if (r < 0 || !p)
return -ENOMEM;
}
return sd_pid_notify_with_fds(pid, unset_environment, p, fds, n_fds);
}
_public_ int sd_booted(void) { _public_ int sd_booted(void) {
/* We test whether the runtime unit file directory has been /* We test whether the runtime unit file directory has been
* created. This takes place in mount-setup.c, so is * created. This takes place in mount-setup.c, so is

View File

@ -290,6 +290,11 @@ int sd_pid_notifyf(pid_t pid, int unset_environment, const char *format, ...) _s
*/ */
int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds); int sd_pid_notify_with_fds(pid_t pid, int unset_environment, const char *state, const int *fds, unsigned n_fds);
/*
Combination of sd_pid_notifyf() and sd_pid_notify_with_fds()
*/
int sd_pid_notifyf_with_fds(pid_t pid, int unset_environment, const int *fds, size_t n_fds, const char *format, ...) _sd_printf_(5,6);
/* /*
Returns > 0 if synchronization with systemd succeeded. Returns < 0 Returns > 0 if synchronization with systemd succeeded. Returns < 0
on error. Returns 0 if $NOTIFY_SOCKET was not set. Note that the on error. Returns 0 if $NOTIFY_SOCKET was not set. Note that the