Skip to content

Commit

Permalink
Introduce sd_notify_barrier
Browse files Browse the repository at this point in the history
  • Loading branch information
kkdwivedi committed Apr 24, 2020
1 parent eecf4f7 commit 763fec3
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/core/manager.c
Expand Up @@ -2284,6 +2284,32 @@ static int manager_dispatch_cgroups_agent_fd(sd_event_source *source, int fd, ui
return 0;
}

static bool manager_process_barrier_fd(const char *buf, FDSet *fds) {
assert(buf);
assert(fds);

_cleanup_strv_free_ char **tags = NULL;

tags = strv_split(buf, NEWLINE);
if (!tags) {
log_oom();
return false;
}

if (strv_find(tags, "BARRIER=1")) {
/* when we process BARRIER=1, we process nothing else */
if (strv_length(tags) > 1)
log_warning("Extra notification messages passed with BARRER=1, ignoring.");

if (fdset_size(fds) > 1)
log_warning("Got extra fds with BARRIER=1, closing them.");

return true;
}

return false;
}

static void manager_invoke_notify_message(
Manager *m,
Unit *u,
Expand Down Expand Up @@ -2416,6 +2442,12 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
/* Make sure it's NUL-terminated. */
buf[n] = 0;

if (fds) {
/* possibly a barrier fd, let's see */
if (manager_process_barrier_fd(buf, fds))
return 0;
}

/* Increase the generation counter used for filtering out duplicate unit invocations. */
m->notifygen++;

Expand Down
36 changes: 36 additions & 0 deletions src/libsystemd/sd-daemon/sd-daemon.c
Expand Up @@ -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>
Expand Down Expand Up @@ -551,6 +552,41 @@ _public_ int sd_pid_notify_with_fds(
return r;
}

_public_ int sd_notify_barrier(int unset_environment, uint64_t timeout) {
_cleanup_close_pair_ int pipe_fd[2] = { -1, -1 };
int r;

if (pipe2(pipe_fd, O_CLOEXEC) < 0) {
r = -errno;
goto finish;
}

struct pollfd pfd = {
.fd = pipe_fd[0],
/* POLLHUP is implicit */
.events = 0,
};

r = sd_pid_notify_with_fds(0, unset_environment, "BARRIER=1", &pipe_fd[1], 1);
if (r <= 0)
goto finish;

pipe_fd[1] = safe_close(pipe_fd[1]);

/* roughly convert to milliseconds, then clamp down */
timeout = timeout/1000 < INT_MAX ? timeout/1000 : INT_MAX;

if (poll(&pfd, 1, (int) timeout) >= 0) {
r = 1;
goto finish;
}

r = -errno;

finish:
return r;
}

_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);
}
Expand Down
9 changes: 9 additions & 0 deletions src/notify/notify.c
Expand Up @@ -213,6 +213,15 @@ static int run(int argc, char* argv[]) {
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"No status data could be sent: $NOTIFY_SOCKET was not set");

/* 5,000,000 µs is 5s */
r = sd_notify_barrier(0, 5000000);
if (r < 0)
return log_error_errno(r, "Failed to create barrier: %m");
if (r == 0)
return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
"No status data could be sent: $NOTIFY_SOCKET was not set");

return 0;
}

Expand Down
13 changes: 13 additions & 0 deletions src/systemd/sd-daemon.h
Expand Up @@ -286,6 +286,19 @@ 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);

/*
Returns > 0 if synchronization with systemd succeeded. Returns < 0
on error. Returns 0 if $NOTIFY_SOCKET was not set. Note that the
timeout parameter of this function call takes the timeout in µs, and
will be passed to poll(2), hence the behaviour will be similar to
poll(2). This function can be called after sending a status message
to systemd, if one needs to synchronize against reception of the
status messages sent before this call is made. Therefore, this
cannot be used to know if the status message was processed
successfully, but to only synchronize against its consumption.
*/
int sd_notify_barrier(int unset_environment, uint64_t timeout);

/*
Returns > 0 if the system was booted with systemd. Returns < 0 on
error. Returns 0 if the system was not booted with systemd. Note
Expand Down

0 comments on commit 763fec3

Please sign in to comment.