diff options
author | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2020-04-28 19:39:27 +0530 |
---|---|---|
committer | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2020-05-01 03:22:47 +0530 |
commit | 4f07ddfa9bc2242eaa6c288a15b8bce4e4383931 (patch) | |
tree | 408c9202f13b2200bb21720e01931b8bfd94ea7b /src/libsystemd/sd-daemon | |
parent | cad67279067b03e64df5421b9a1e9fef077863d9 (diff) | |
download | systemd-4f07ddfa9bc2242eaa6c288a15b8bce4e4383931.tar.gz |
Introduce sd_notify_barrier
This adds the sd_notify_barrier function, to allow users to synchronize against
the reception of sd_notify(3) status messages. It acts as a synchronization
point, and a successful return gurantees that all previous messages have been
consumed by the manager. This can be used to eliminate race conditions where
the sending process exits too early for systemd to associate its PID to a
cgroup and attribute the status message to a unit correctly.
systemd-notify now uses this function for proper notification delivery and be
useful for NotifyAccess=all units again in user mode, or in cases where it
doesn't have a control process as parent.
Fixes: #2739
Diffstat (limited to 'src/libsystemd/sd-daemon')
-rw-r--r-- | src/libsystemd/sd-daemon/sd-daemon.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 4cd71cb2d3..587a1f2595 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -4,6 +4,7 @@ #include <limits.h> #include <mqueue.h> #include <netinet/in.h> +#include <poll.h> #include <stdarg.h> #include <stddef.h> #include <stdio.h> @@ -23,6 +24,7 @@ #include "process-util.h" #include "socket-util.h" #include "strv.h" +#include "time-util.h" #include "util.h" #define SNDBUF_SIZE (8*1024*1024) @@ -551,6 +553,34 @@ finish: return r; } +_public_ int sd_notify_barrier(int unset_environment, uint64_t timeout) { + _cleanup_close_pair_ int pipe_fd[2] = { -1, -1 }; + struct timespec ts; + int r; + + if (pipe2(pipe_fd, O_CLOEXEC) < 0) + return -errno; + + r = sd_pid_notify_with_fds(0, unset_environment, "BARRIER=1", &pipe_fd[1], 1); + if (r <= 0) + return r; + + pipe_fd[1] = safe_close(pipe_fd[1]); + + struct pollfd pfd = { + .fd = pipe_fd[0], + /* POLLHUP is implicit */ + .events = 0, + }; + r = ppoll(&pfd, 1, timeout == UINT64_MAX ? NULL : timespec_store(&ts, timeout), NULL); + if (r < 0) + return -errno; + if (r == 0) + return -ETIMEDOUT; + + return 1; +} + _public_ int sd_pid_notify(pid_t pid, int unset_environment, const char *state) { return sd_pid_notify_with_fds(pid, unset_environment, state, NULL, 0); } |