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 22, 2020
1 parent eecf4f7 commit 8ea8cab
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
72 changes: 72 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,77 @@ _public_ int sd_pid_notify_with_fds(
return r;
}

_public_ int sd_notify_barrier(int timeout) {
union sockaddr_union sockaddr;
char byte = 0;
struct iovec iovec = {
.iov_base = &byte,
.iov_len = 1,
};
struct msghdr msghdr = {
.msg_iov = &iovec,
.msg_iovlen = 1,
.msg_name = &sockaddr,
};

_cleanup_close_pair_ int pipe_fd[2] = { -1, -1 };
_cleanup_close_ int fd = -1;
struct cmsghdr *cmsg = NULL;
const char *e;
int r;

e = getenv("NOTIFY_SOCKET");
if (!e)
return 0;

r = sockaddr_un_set_path(&sockaddr.un, e);
if (r < 0)
goto finish;
msghdr.msg_namelen = r;

fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
if (fd < 0) {
r = -errno;
goto finish;
}

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

msghdr.msg_controllen = CMSG_SPACE(sizeof(int));

msghdr.msg_control = alloca0(msghdr.msg_controllen);

cmsg = CMSG_FIRSTHDR(&msghdr);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int));

memcpy(CMSG_DATA(cmsg), &pipe_fd[1], sizeof(int));

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

/* Send the write end and wait for systemd to close it */
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) >= 0) {
safe_close(pipe_fd[1]);
pipe_fd[1] = -1;
if (poll(&pfd, 1, 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
8 changes: 8 additions & 0 deletions src/notify/notify.c
Expand Up @@ -213,6 +213,14 @@ 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");

r = sd_notify_barrier(5000);
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 is directly passed to the poll(2)
system call, hence the requirements and behaviour is 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. Thus, 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 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 8ea8cab

Please sign in to comment.