mirror of
https://github.com/troglobit/finit.git
synced 2026-10-01 05:22:48 +07:00
test: update serv daemon to use proper systemd abstract socket
This commit introduces a stripped down sd_notify(), taken from the systemd man page example, which is used by the serv daemon in lieu of the previous broken implementation. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
noinst_PROGRAMS = serv
|
||||
|
||||
serv_SOURCES = serv.c
|
||||
serv_SOURCES = serv.c sd-daemon.c sd-daemon.h
|
||||
serv_CPPFLAGS = -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -D_GNU_SOURCE -D_DEFAULT_SOURCE
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/* SPDX-License-Identifier: MIT-0 */
|
||||
|
||||
/*
|
||||
* systemd notify protocol, supporting readiness notification on startup
|
||||
* and reloading, according to the protocol defined at:
|
||||
* https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
|
||||
*
|
||||
* This protocol is guaranteed to be stable as per:
|
||||
* https://systemd.io/PORTABILITY_AND_STABILITY/
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE 1
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
* NOTE: As per spec., this function does not return POSIX OK(0) but
|
||||
* rather "a positive value", i.e., 1.
|
||||
*/
|
||||
int sd_notify(int unset_environment, const char *state)
|
||||
{
|
||||
struct sockaddr_un sun = {
|
||||
.sun_family = AF_UNIX,
|
||||
};
|
||||
size_t len, sun_len;
|
||||
const char *path;
|
||||
ssize_t written;
|
||||
int sd;
|
||||
|
||||
if (!state)
|
||||
return -EINVAL;
|
||||
|
||||
len = strlen(state);
|
||||
if (len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
/* If the variable is not set, the protocol is a noop */
|
||||
path = getenv("NOTIFY_SOCKET");
|
||||
if (!path)
|
||||
return 0; /* Not set? Nothing to do */
|
||||
|
||||
/* Only AF_UNIX is supported, with path or abstract sockets */
|
||||
if (path[0] != '/' && path[0] != '@')
|
||||
return -EAFNOSUPPORT;
|
||||
|
||||
/* Ensure there is room for NUL byte */
|
||||
sun_len = strlen(path);
|
||||
if (sun_len >= sizeof(sun.sun_path))
|
||||
return -E2BIG;
|
||||
|
||||
strlcpy(sun.sun_path, path, sizeof(sun.sun_path));
|
||||
if (sun.sun_path[0] == '@')
|
||||
sun.sun_path[0] = 0;
|
||||
|
||||
sd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
|
||||
if (sd == -1)
|
||||
return -errno;
|
||||
|
||||
if (connect(sd, (struct sockaddr *)&sun, offsetof(struct sockaddr_un, sun_path) + sun_len) == -1) {
|
||||
close(sd);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (unset_environment)
|
||||
unsetenv("NOTIFY_SOCKET");
|
||||
|
||||
written = write(sd, state, len);
|
||||
if (written != (ssize_t) len) {
|
||||
close(sd);
|
||||
return written < 0 ? -errno : -EPROTO;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef SD_DAEMON_H_
|
||||
#define SD_DAEMON_H_
|
||||
|
||||
int sd_notify(int unset_environment, const char *state);
|
||||
|
||||
#endif /* SD_DAEMON_H_ */
|
||||
+23
-11
@@ -16,6 +16,7 @@
|
||||
#include <sysexits.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include "sd-daemon.h"
|
||||
|
||||
#define PROGNM "serv"
|
||||
|
||||
@@ -160,7 +161,7 @@ static int usage(int rc)
|
||||
" -h Show help text (this)\n"
|
||||
" -i IDENT Change process identity, incl. logs, pidfile, etc.\n"
|
||||
" -n Run in foreground\n"
|
||||
" -N SOCK Send 'READY=1\\n' on $NOTIFY_SOCKET or SOCK\n"
|
||||
" -N SOCK Send '\\n' on SOCK (integer), for s6 readiness\n"
|
||||
" -p Create PID file despite running in foreground\n"
|
||||
" -P FILE Create PID file using FILE\n"
|
||||
" -r SVC Call initctl to restart service SVC (self)\n"
|
||||
@@ -170,6 +171,8 @@ static int usage(int rc)
|
||||
"to let the rest of the system know it's done. When the program runs\n"
|
||||
"in the foreground it does not create a PID file by default.\n"
|
||||
"\n"
|
||||
"When acting as a systemd daemon, this program expects NOTIFY_SOCKET\n"
|
||||
"\n"
|
||||
"Regardless of how This daemon is started it provides a single service\n"
|
||||
"to others, spice ... guarded by sandworms.\n",
|
||||
ident);
|
||||
@@ -256,13 +259,13 @@ int main(int argc, char *argv[])
|
||||
if (do_pidfile > 0)
|
||||
pidfile(pidfn);
|
||||
|
||||
if (!do_notify) {
|
||||
const char *sock = getenv("NOTIFY_SOCKET");
|
||||
if (!do_notify && getenv("NOTIFY_SOCKET"))
|
||||
do_notify = 1;
|
||||
|
||||
/* systemd style */
|
||||
if (sock)
|
||||
do_notify = atoi(sock);
|
||||
}
|
||||
if (do_notify)
|
||||
inf("Will notify %s ...", notify_s6 ? "s6" : "systemd");
|
||||
else
|
||||
inf("No notify socket ...");
|
||||
|
||||
if (do_crash) {
|
||||
inf("Simulating crash, exiting with code %d", EX_SOFTWARE);
|
||||
@@ -279,15 +282,24 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (reloading) {
|
||||
if (do_notify > 0) {
|
||||
/* Issue #343: see notify.sh test for more details */
|
||||
inf("Delaying notify by 3 seconds for notify.sh ...");
|
||||
sleep(3);
|
||||
inf("Notifying Finit on socket %d, READY=1", do_notify);
|
||||
if (write(do_notify, "READY=1\n", 8) == -1)
|
||||
err(1, "Failed sending ready notification to Finit");
|
||||
|
||||
if (notify_s6) {
|
||||
inf("Notifying Finit on socket %d", do_notify);
|
||||
if (write(do_notify, "\n", 1) < 1)
|
||||
err(1, "Failed sending ready notification to Finit");
|
||||
inf("s6 notify, closing socket %d ...", do_notify);
|
||||
close(do_notify);
|
||||
if (close(do_notify))
|
||||
err(1, "Failed closing notify socket");
|
||||
do_notify = 0;
|
||||
} else {
|
||||
int rc;
|
||||
|
||||
inf("Notifying Finit on NOTIFY_SOCKET");
|
||||
rc = sd_notify(0, "READY=1");
|
||||
inf("sd_notify () => %d", rc);
|
||||
}
|
||||
}
|
||||
if (do_pidfile > 0)
|
||||
|
||||
Reference in New Issue
Block a user