]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-daemon: add sd_pid_notifyf_with_fds()
authorLennart Poettering <lennart@poettering.net>
Fri, 14 Apr 2023 15:48:47 +0000 (17:48 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 25 Apr 2023 15:38:57 +0000 (17:38 +0200)
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.

man/rules/meson.build
man/sd_notify.xml
src/libsystemd/libsystemd.sym
src/libsystemd/sd-daemon/sd-daemon.c
src/systemd/sd-daemon.h

index ca3b471281fbacb571c5407587ede89ca8e4ec12..13d2bd9b58a8fe90d14b39c12caa2dcea506ebb4 100644 (file)
@@ -808,7 +808,8 @@ manpages = [
    'sd_notifyf',
    'sd_pid_notify',
    '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_pid_get_owner_uid',
index f93542e329be7d3672812126750870b642cd4013..b82d145860abbe23fd6667f54c180203a8aa437d 100644 (file)
@@ -22,6 +22,7 @@
     <refname>sd_pid_notify</refname>
     <refname>sd_pid_notifyf</refname>
     <refname>sd_pid_notify_with_fds</refname>
+    <refname>sd_pid_notifyf_with_fds</refname>
     <refname>sd_notify_barrier</refname>
     <refpurpose>Notify service manager about start-up completion and other service status changes</refpurpose>
   </refnamediv>
         <paramdef>unsigned <parameter>n_fds</parameter></paramdef>
       </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>
         <funcdef>int <function>sd_notify_barrier</function></funcdef>
         <paramdef>int <parameter>unset_environment</parameter></paramdef>
     able to properly attribute the message to the unit, and thus will ignore it, even if
     <varname>NotifyAccess=</varname><option>all</option> is set for it.</para>
 
-    <para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of notifications
-    to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as a synchronization point
-    and ensures all notifications sent before this call have been picked up by the service manager when it returns
-    successfully. Use of <function>sd_notify_barrier()</function> is needed for clients which are not invoked by the
-    service manager, otherwise this synchronization mechanism is unnecessary for attribution of notifications to the
-    unit.</para>
+    <para>Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of
+    notifications to units correctly, <function>sd_notify_barrier()</function> may be used. This call acts as
+    a synchronization point and ensures all notifications sent before this call have been picked up by the
+    service manager when it returns successfully. Use of <function>sd_notify_barrier()</function> is needed
+    for clients which are not invoked by the service manager, otherwise this synchronization mechanism is
+    unnecessary for attribution of notifications to the unit.</para>
 
     <para><function>sd_notifyf()</function> is similar to <function>sd_notify()</function> but takes a
     <function>printf()</function>-like format string plus arguments.</para>
     that file descriptors sent to the service manager on a message without <literal>FDSTORE=1</literal> are
     immediately closed on reception.</para>
 
+    <para><function>sd_pid_notifyf_with_fds()</function> is a combination of
+    <function>sd_pid_notify_with_fds()</function> and <function>sd_notifyf()</function>, i.e. it accepts both
+    a PID and a set of file descriptors as input, and processes a format string to generate the state
+    string.</para>
+
     <para><function>sd_notify_barrier()</function> allows the caller to synchronize against reception of
     previously sent notification messages and uses the <varname>BARRIER=1</varname> command. It takes a
     relative <varname>timeout</varname> value in microseconds which is passed to
index 53db234a0c32ff4a547600b9e5bf8d63bf079b38..76fa1e0e32b03e07484bb182d74ea1b67cacfd12 100644 (file)
@@ -818,4 +818,5 @@ global:
         sd_session_get_username;
         sd_session_get_start_time;
         sd_uid_get_login_time;
+        sd_pid_notifyf_with_fds;
 } LIBSYSTEMD_253;
index f2f295d6e4e09f0181c1ca083d77c90efc796fb4..eec6fb64efe1773e64a544c846d089c351d4ea0c 100644 (file)
@@ -667,6 +667,36 @@ _public_ int sd_notifyf(int unset_environment, const char *format, ...) {
         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) {
         /* We test whether the runtime unit file directory has been
          * created. This takes place in mount-setup.c, so is
index 6f88cf02fae8b26a4ce32fbc8bab5c00c0dfb8a1..a8b40ff1f8c2c23f431d5868f25df69238713147 100644 (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);
 
+/*
+  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
   on error. Returns 0 if $NOTIFY_SOCKET was not set. Note that the