summaryrefslogtreecommitdiff
path: root/src/libsystemd/sd-daemon
diff options
context:
space:
mode:
authorKumar Kartikeya Dwivedi <memxor@gmail.com>2020-04-28 19:39:27 +0530
committerKumar Kartikeya Dwivedi <memxor@gmail.com>2020-05-01 03:22:47 +0530
commit4f07ddfa9bc2242eaa6c288a15b8bce4e4383931 (patch)
tree408c9202f13b2200bb21720e01931b8bfd94ea7b /src/libsystemd/sd-daemon
parentcad67279067b03e64df5421b9a1e9fef077863d9 (diff)
downloadsystemd-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.c30
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);
}