aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-04-10 12:31:39 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-04-10 12:31:39 +0000
commit8476eaf087910edcfb2db1c7f997b99c2b3e95d5 (patch)
treea25f6d980a35f3123efc4399d6d45576640a52c9
parentfacc1fb44783a1c66070403ae70343b1ab9858ee (diff)
downloads6-8476eaf087910edcfb2db1c7f997b99c2b3e95d5.tar.gz
s6-notify-socket-from-fd: use BARRIER=1
-rw-r--r--.gitignore2
-rw-r--r--doc/s6-notify-socket-from-fd.html1
-rw-r--r--src/supervision/s6-notify-socket-from-fd.c87
3 files changed, 69 insertions, 21 deletions
diff --git a/.gitignore b/.gitignore
index 6070361..3063492 100644
--- a/.gitignore
+++ b/.gitignore
@@ -80,3 +80,5 @@
/s6-instance-status
/s6-instance-list
/s6-background-watch
+/s6-notify-socket-from-fd
+/s6-notify-fd-from-socket
diff --git a/doc/s6-notify-socket-from-fd.html b/doc/s6-notify-socket-from-fd.html
index a1f68d2..cf5b769 100644
--- a/doc/s6-notify-socket-from-fd.html
+++ b/doc/s6-notify-socket-from-fd.html
@@ -82,6 +82,7 @@ differentiated for clarity in the source code:
<ul>
<li> 0: service readiness achieved and notification sent </li>
+ <li> 1: service exited before becoming ready </li>
<li> 99: timed out before readiness was achieved </li>
<li> 111: system call failed </li>
</ul>
diff --git a/src/supervision/s6-notify-socket-from-fd.c b/src/supervision/s6-notify-socket-from-fd.c
index c443b40..97c8cb3 100644
--- a/src/supervision/s6-notify-socket-from-fd.c
+++ b/src/supervision/s6-notify-socket-from-fd.c
@@ -1,5 +1,7 @@
/* ISC license. */
+#include <skalibs/nonposix.h>
+
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
@@ -8,6 +10,7 @@
#include <sys/socket.h>
#include <sys/un.h>
+#include <skalibs/gccattributes.h>
#include <skalibs/uint64.h>
#include <skalibs/types.h>
#include <skalibs/bytestr.h>
@@ -36,32 +39,75 @@ enum gola_e
GOLA_N
} ;
-static inline int ipc_sendto (int fd, char const *s, size_t len, char const *path)
+union aligner_u
{
- struct sockaddr_un sa ;
- size_t l = strlen(path) ;
- if (l > IPCPATH_MAX) return (errno = ENAMETOOLONG, 0) ;
- memset(&sa, 0, sizeof sa) ;
- sa.sun_family = AF_UNIX ;
- memcpy(sa.sun_path, path, l+1) ;
- if (path[0] == '@') sa.sun_path[0] = 0 ;
- return sendto(fd, s, len, MSG_NOSIGNAL, (struct sockaddr *)&sa, sizeof sa) >= 0 ;
+ struct cmsghdr cmsghdr ;
+ int i ;
+} ;
+
+static inline ssize_t fd_sendmsg (int fd, struct msghdr const *hdr)
+{
+ ssize_t r ;
+ int e = errno ;
+ do r = sendmsg(fd, hdr, MSG_NOSIGNAL) ;
+ while (r == -1 && errno == EINTR) ;
+ if (r <= 0) return 0 ;
+ errno = e ;
+ return 1 ;
}
-static inline void notify_systemd (pid_t pid, char const *socketpath)
+static inline void notify_systemd (pid_t pid, char const *path, tain const *deadline) gccattr_noreturn ;
+static inline void notify_systemd (pid_t pid, char const *path, tain const *deadline)
{
- size_t n = 16 ;
- char fmt[16 + PID_FMT] = "READY=1\nMAINPID=" ;
- int fd = ipc_datagram_b() ;
+ iopause_fd x = { .events = IOPAUSE_READ } ;
+ int p[2] ;
+ int fd ;
+ size_t n = 26 ;
+ char fmt[26 + PID_FMT] = "READY=1\nBARRIER=1\nMAINPID=" ;
+ struct sockaddr_un addr = { 0 } ;
+ size_t l = strlen(path) ;
+ struct iovec v = { .iov_base = fmt, .iov_len = n } ;
+ union aligner_u ancilbuf[1 + (CMSG_SPACE(sizeof(int)) - 1) / sizeof(union aligner_u)] ;
+ struct msghdr hdr =
+ {
+ .msg_name = &addr,
+ .msg_namelen = sizeof addr,
+ .msg_iov = &v,
+ .msg_iovlen = 1,
+ .msg_control = ancilbuf,
+ .msg_controllen = CMSG_SPACE(sizeof(int))
+ } ;
+ struct cmsghdr *c = CMSG_FIRSTHDR(&hdr) ;
+ if (l > IPCPATH_MAX)
+ {
+ errno = ENAMETOOLONG ;
+ strerr_diefu2sys(111, "send a message to ", path) ;
+ }
+ fd = ipc_datagram_b() ;
if (fd == -1) strerr_diefu1sys(111, "create socket") ;
+ if (pipecoe(p) == -1) strerr_diefu1sys(111, "pipe") ;
+ addr.sun_family = AF_UNIX ;
+ memcpy(addr.sun_path, path, l+1) ;
+ if (path[0] == '@') addr.sun_path[0] = 0 ;
n += pid_fmt(fmt + n, pid) ;
fmt[n++] = '\n' ;
- if (!ipc_sendto(fd, fmt, n, socketpath))
- strerr_diefu2sys(111, "send notification message to ", socketpath) ;
+ memset(hdr.msg_control, 0, hdr.msg_controllen) ;
+ c->cmsg_level = SOL_SOCKET ;
+ c->cmsg_type = SCM_RIGHTS ;
+ c->cmsg_len = CMSG_LEN(sizeof(int)) ;
+ memcpy(CMSG_DATA(c), p+1, sizeof(int)) ;
+
+ if (!fd_sendmsg(fd, &hdr)) strerr_diefu2sys(111, "send notification message to ", path) ;
fd_close(fd) ;
+ fd_close(p[1]) ;
+ x.fd = p[0] ;
+ fd = iopause_g(&x, 1, deadline) ;
+ if (fd == -1) strerr_diefu1sys(111, "iopause") ;
+ _exit(fd ? 0 : 99) ;
}
-static inline int run_child (int fd, unsigned int timeout, pid_t pid, char const *s)
+static inline void run_child (int fd, unsigned int timeout, pid_t pid, char const *s) gccattr_noreturn ;
+static inline void run_child (int fd, unsigned int timeout, pid_t pid, char const *s)
{
char dummy[4096] ;
iopause_fd x = { .fd = fd, .events = IOPAUSE_READ } ;
@@ -73,16 +119,15 @@ static inline int run_child (int fd, unsigned int timeout, pid_t pid, char const
{
int r = iopause_g(&x, 1, &deadline) ;
if (r == -1) strerr_diefu1sys(111, "iopause") ;
- if (!r) return 99 ;
+ if (!r) _exit(99) ;
r = sanitize_read(fd_read(fd, dummy, 4096)) ;
if (r < 0)
- if (errno == EPIPE) return 1 ;
+ if (errno == EPIPE) _exit(1) ;
else strerr_diefu1sys(111, "read from parent") ;
else if (r && memchr(dummy, '\n', r)) break ;
}
fd_close(fd) ;
- notify_systemd(pid, s) ;
- return 0 ;
+ notify_systemd(pid, s, &deadline) ;
}
int main (int argc, char const *const *argv)
@@ -128,7 +173,7 @@ int main (int argc, char const *const *argv)
{
PROG = "s6-notify-socket-from-fd (child)" ;
fd_close(p[1]) ;
- return run_child(p[0], timeout, parent, s) ;
+ run_child(p[0], timeout, parent, s) ;
}
fd_close(p[0]) ;
if (fd_move(fd, p[1]) == -1) strerr_diefu1sys(111, "fd_move") ;