From: Lennart Poettering Date: Fri, 14 Apr 2023 15:48:47 +0000 (+0200) Subject: sd-daemon: add sd_pid_notifyf_with_fds() X-Git-Tag: v254-rc1~636 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4054d76151678edc7c6b77ebdebb9a32d1dc11c9;p=thirdparty%2Fsystemd.git 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. --- diff --git a/man/rules/meson.build b/man/rules/meson.build index ca3b471281f..13d2bd9b58a 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -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', diff --git a/man/sd_notify.xml b/man/sd_notify.xml index f93542e329b..b82d145860a 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -22,6 +22,7 @@ sd_pid_notify sd_pid_notifyf sd_pid_notify_with_fds + sd_pid_notifyf_with_fds sd_notify_barrier Notify service manager about start-up completion and other service status changes @@ -67,6 +68,16 @@ unsigned n_fds + + int sd_pid_notifyf_with_fds + pid_t pid + int unset_environment + const int *fds + size_t n_fds + const char *format + … + + int sd_notify_barrier int unset_environment @@ -326,12 +337,12 @@ able to properly attribute the message to the unit, and thus will ignore it, even if NotifyAccess= is set for it. - Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of notifications - to units correctly, sd_notify_barrier() 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 sd_notify_barrier() 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. + Hence, to eliminate all race conditions involving lookup of the client's unit and attribution of + notifications to units correctly, sd_notify_barrier() 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 sd_notify_barrier() 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. sd_notifyf() is similar to sd_notify() but takes a printf()-like format string plus arguments. @@ -352,6 +363,11 @@ that file descriptors sent to the service manager on a message without FDSTORE=1 are immediately closed on reception. + sd_pid_notifyf_with_fds() is a combination of + sd_pid_notify_with_fds() and sd_notifyf(), 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. + sd_notify_barrier() allows the caller to synchronize against reception of previously sent notification messages and uses the BARRIER=1 command. It takes a relative timeout value in microseconds which is passed to diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 53db234a0c3..76fa1e0e32b 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -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; diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index f2f295d6e4e..eec6fb64efe 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -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 diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h index 6f88cf02fae..a8b40ff1f8c 100644 --- a/src/systemd/sd-daemon.h +++ b/src/systemd/sd-daemon.h @@ -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