Comment by ~jameshilliard on ~kennylevinsen/seatd
I wrote a quick patch that implements sd_notify with status and error code reporting.
Comment by ~jameshilliard on ~kennylevinsen/seatd
There's a lot of fallback/special handling in the function parsing NOTIFY_SOCKET from what I can tell.
Comment by ~jameshilliard on ~kennylevinsen/seatd
the service file can specify $NOTIFY_SOCKET as the -n parameter.
How would that work? The normal
sd_notify
seems to require some logic around parsing/converting theNOTIFY_SOCKET
env variable.
Comment by ~jameshilliard on ~kennylevinsen/seatd
I do not intend on adding ifdefs and dependencies just to write a fixed string to an fd.
The implementation seems to be slightly more complex than that, not sure if this handles all the edge cases properly but I think it would be something like this.
diff --git a/seatd/seatd.c b/seatd/seatd.c index f88e6c9..07b628b 100644 --- a/seatd/seatd.c +++ b/seatd/seatd.c @@ -56,6 +56,74 @@ error: return -1; } +union sockaddr_union { + struct sockaddr sa; + struct sockaddr_un un; +}; + +static int systemd_notify(const char *state) { + int fd = -1, r; + struct msghdr msghdr; + struct iovec iovec; + union sockaddr_union sockaddr; + const char *e; + + if (!state) { + r = -EINVAL; + goto finish; + } + + e = getenv("NOTIFY_SOCKET"); + if (!e) + return 0; + + /* Must be an abstract socket, or an absolute path */ + if ((e[0] != '@' && e[0] != '/') || e[1] == 0) { + r = -EINVAL; + goto finish; + } + + fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); + if (fd < 0) { + r = -errno; + goto finish; + } + + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sa.sa_family = AF_UNIX; + strncpy(sockaddr.un.sun_path, e, sizeof(sockaddr.un.sun_path)); + + if (sockaddr.un.sun_path[0] == '@') + sockaddr.un.sun_path[0] = 0; + + memset(&iovec, 0, sizeof(iovec)); + iovec.iov_base = (char*) state; + iovec.iov_len = strlen(state); + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = &sockaddr; + msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + strlen(e); + + if (msghdr.msg_namelen > sizeof(struct sockaddr_un)) + msghdr.msg_namelen = sizeof(struct sockaddr_un); + + msghdr.msg_iov = &iovec; + msghdr.msg_iovlen = 1; + + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) { + r = -errno; + goto finish; + } + + r = 1; + +finish: + if (fd >= 0) + close(fd); + + return r; +} + int main(int argc, char *argv[]) { const char *usage = "Usage: seatd [options]\n" "\n" @@ -193,6 +261,8 @@ int main(int argc, char *argv[]) { log_info("seatd started"); + systemd_notify("READY=1\n"); + if (readiness != -1) { if (write(readiness, "\n", 1) == -1) { log_errorf("Could not write readiness signal: %s\n", strerror(errno));
Comment by ~jameshilliard on ~kennylevinsen/seatd
seatd offers readiness through the s6 protocol - see -n.
Best I can tell systemd services do not support s6 protocol.
Linking with libsystemd just for notify seems silly though.
I think linking to libsystemd should be fine, any systemd based system should always have libsystemd available and we pull libsystemd in when building seatd with
libseat-logind
support already so it's not like we'd be adding an entirely new dependency.
Ticket created by ~jameshilliard on ~kennylevinsen/seatd
Currently the systemd service for seatd uses
Type=simple
.This is somewhat problematic as it doesn't provide a method to inform the systemd service manager when the seatd service is actually started up and fully ready, as such a dependent service may be started before the seatd daemon is ready and the seatd socket is available resulting in that dependent service failing to start up.
See documentation for
sd_notify
.From my understanding we should have a meson build option to enable
sd_notify
support when libsystemd is present as well as change the exampleseatd.service
file to useType=notify
instead ofType=simple
.