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
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user