summaryrefslogtreecommitdiffstats
path: root/upstream/fedora-rawhide/man3/sd_notify.3
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/fedora-rawhide/man3/sd_notify.3')
-rw-r--r--upstream/fedora-rawhide/man3/sd_notify.3370
1 files changed, 353 insertions, 17 deletions
diff --git a/upstream/fedora-rawhide/man3/sd_notify.3 b/upstream/fedora-rawhide/man3/sd_notify.3
index 204db883..dc26c47a 100644
--- a/upstream/fedora-rawhide/man3/sd_notify.3
+++ b/upstream/fedora-rawhide/man3/sd_notify.3
@@ -1,5 +1,5 @@
'\" t
-.TH "SD_NOTIFY" "3" "" "systemd 255" "sd_notify"
+.TH "SD_NOTIFY" "3" "" "systemd 256~rc3" "sd_notify"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -57,7 +57,7 @@ will unset the
\fI$NOTIFY_SOCKET\fR
environment variable before returning (regardless of whether the function call itself succeeded or not)\&. Further calls to
\fBsd_notify()\fR
-will then fail, and the variable is no longer inherited by child processes\&.
+will then silently do nothing, and the variable is no longer inherited by child processes\&.
.PP
The
\fIstate\fR
@@ -223,7 +223,7 @@ The exit status of a service or the manager itself\&. Note that
\fBsystemd\fR
currently does not consume this value when sent by services, so this assignment is only informational\&. The manager will send this notification to
\fIits\fR
-notification socket, which may be used to to collect an exit status from the system (a container or VM) as it shuts down\&. For example,
+notification socket, which may be used to collect an exit status from the system (a container or VM) as it shuts down\&. For example,
\fBmkosi\fR(1)
makes use of this\&. The value to return may be set via the
\fBsystemctl\fR(1)
@@ -367,7 +367,7 @@ Added in version 233\&.
FDPOLL=0
.RS 4
When used in combination with
-\fIFDSTORE=1\fR, disables polling of the stored file descriptors regardless of whether or not they are pollable\&. As this option disables automatic cleanup of the stored file descriptors on EPOLLERR and EPOLLHUP, care must be taken to ensure proper manual cleanup\&. Use of this option is not generally recommended except for when automatic cleanup has unwanted behavior such as prematurely discarding file descriptors from the store\&.
+\fIFDSTORE=1\fR, disables polling of the submitted file descriptors regardless of whether or not they are pollable\&. As this option disables automatic cleanup of the submitted file descriptors on EPOLLERR and EPOLLHUP, care must be taken to ensure proper manual cleanup\&. Use of this option is not generally recommended except for when automatic cleanup has unwanted behavior such as prematurely discarding file descriptors from the store\&.
.sp
Added in version 246\&.
.RE
@@ -381,9 +381,13 @@ command will only happen after all previous notification messages sent before th
Added in version 246\&.
.RE
.PP
-The notification messages sent by services are interpreted by the service manager\&. Unknown assignments may be logged, but are otherwise ignored\&. Thus, it is not useful to send assignments which are not in this list\&. The service manager also sends some messages to
+The notification messages sent by services are interpreted by the service manager\&. Unknown assignments are ignored\&. Thus, it is safe (but often without effect) to send assignments which are not in this list\&. The protocol is extensible, but care should be taken to ensure private extensions are recognizable as such\&. Specifically, it is recommend to prefix them with
+"X_"
+followed by some namespace identifier\&. The service manager also sends some messages to
\fIits\fR
-notification socket, which are then consumed by the machine or container manager\&.
+notification socket, which may then consumed by a supervising machine or container manager further up the stack\&. The service manager sends a number of extension fields, for example
+\fIX_SYSTEMD_UNIT_ACTIVE=\fR, for details see
+\fBsystemd\fR(1)\&.
.SH "RETURN VALUE"
.PP
On failure, these calls return a negative errno\-style error code\&. If
@@ -422,9 +426,347 @@ address, which is useful for hypervisors/VMMs or other processes on the host to
over
\fBAF_VSOCK\fR,
\fBSOCK_SEQPACKET\fR
-will be used instead\&. The address should be in the form:
+will be used instead\&.
+"vsock\-stream",
+"vsock\-dgram"
+and
+"vsock\-seqpacket"
+can be used instead of
+"vsock"
+to force usage of the corresponding socket type\&. The address should be in the form:
"vsock:CID:PORT"\&. Note that unlike other uses of vsock, the CID is mandatory and cannot be
"VMADDR_CID_ANY"\&. Note that PID1 will send the VSOCK packets from a privileged port (i\&.e\&.: lower than 1024), as an attempt to address concerns that unprivileged processes in the guest might try to send malicious notifications to the host, driving it to make destructive decisions based on them\&.
+.SS "Standalone Implementations"
+.PP
+Note that, while using this library should be preferred in order to avoid code duplication, it is also possible to reimplement the simple readiness notification protocol without external dependencies, as demonstrated in the following self\-contained examples from several languages:
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBC\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+/* SPDX\-License\-Identifier: MIT\-0 */
+
+/* Implement the systemd notify protocol without external dependencies\&.
+ * Supports both readiness notification on startup and on 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 <sys/socket\&.h>
+#include <sys/un\&.h>
+#include <time\&.h>
+#include <unistd\&.h>
+
+#define _cleanup_(f) __attribute__((cleanup(f)))
+
+static void closep(int *fd) {
+ if (!fd || *fd < 0)
+ return;
+
+ close(*fd);
+ *fd = \-1;
+}
+
+static int notify(const char *message) {
+ union sockaddr_union {
+ struct sockaddr sa;
+ struct sockaddr_un sun;
+ } socket_addr = {
+ \&.sun\&.sun_family = AF_UNIX,
+ };
+ size_t path_length, message_length;
+ _cleanup_(closep) int fd = \-1;
+ const char *socket_path;
+
+ /* Verify the argument first */
+ if (!message)
+ return \-EINVAL;
+
+ message_length = strlen(message);
+ if (message_length == 0)
+ return \-EINVAL;
+
+ /* If the variable is not set, the protocol is a noop */
+ socket_path = getenv("NOTIFY_SOCKET");
+ if (!socket_path)
+ return 0; /* Not set? Nothing to do */
+
+ /* Only AF_UNIX is supported, with path or abstract sockets */
+ if (socket_path[0] != \*(Aq/\*(Aq && socket_path[0] != \*(Aq@\*(Aq)
+ return \-EAFNOSUPPORT;
+
+ path_length = strlen(socket_path);
+ /* Ensure there is room for NUL byte */
+ if (path_length >= sizeof(socket_addr\&.sun\&.sun_path))
+ return \-E2BIG;
+
+ memcpy(socket_addr\&.sun\&.sun_path, socket_path, path_length);
+
+ /* Support for abstract socket */
+ if (socket_addr\&.sun\&.sun_path[0] == \*(Aq@\*(Aq)
+ socket_addr\&.sun\&.sun_path[0] = 0;
+
+ fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ return \-errno;
+
+ if (connect(fd, &socket_addr\&.sa, offsetof(struct sockaddr_un, sun_path) + path_length) != 0)
+ return \-errno;
+
+ ssize_t written = write(fd, message, message_length);
+ if (written != (ssize_t) message_length)
+ return written < 0 ? \-errno : \-EPROTO;
+
+ return 1; /* Notified! */
+}
+
+static int notify_ready(void) {
+ return notify("READY=1");
+}
+
+static int notify_reloading(void) {
+ /* A buffer with length sufficient to format the maximum UINT64 value\&. */
+ char reload_message[sizeof("RELOADING=1\enMONOTONIC_USEC=18446744073709551615")];
+ struct timespec ts;
+ uint64_t now;
+
+ /* Notify systemd that we are reloading, including a CLOCK_MONOTONIC timestamp in usec
+ * so that the program is compatible with a Type=notify\-reload service\&. */
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
+ return \-errno;
+
+ if (ts\&.tv_sec < 0 || ts\&.tv_nsec < 0 ||
+ (uint64_t) ts\&.tv_sec > (UINT64_MAX \- (ts\&.tv_nsec / 1000ULL)) / 1000000ULL)
+ return \-EINVAL;
+
+ now = (uint64_t) ts\&.tv_sec * 1000000ULL + (uint64_t) ts\&.tv_nsec / 1000ULL;
+
+ if (snprintf(reload_message, sizeof(reload_message), "RELOADING=1\enMONOTONIC_USEC=%" PRIu64, now) < 0)
+ return \-EINVAL;
+
+ return notify(reload_message);
+}
+
+static int notify_stopping(void) {
+ return notify("STOPPING=1");
+}
+
+static volatile sig_atomic_t reloading = 0;
+static volatile sig_atomic_t terminating = 0;
+
+static void signal_handler(int sig) {
+ if (sig == SIGHUP)
+ reloading = 1;
+ else if (sig == SIGINT || sig == SIGTERM)
+ terminating = 1;
+}
+
+int main(int argc, char **argv) {
+ struct sigaction sa = {
+ \&.sa_handler = signal_handler,
+ \&.sa_flags = SA_RESTART,
+ };
+ int r;
+
+ /* Setup signal handlers */
+ sigemptyset(&sa\&.sa_mask);
+ sigaction(SIGHUP, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+
+ /* Do more service initialization work here \&... */
+
+ /* Now that all the preparations steps are done, signal readiness */
+
+ r = notify_ready();
+ if (r < 0) {
+ fprintf(stderr, "Failed to notify readiness to $NOTIFY_SOCKET: %s\en", strerror(\-r));
+ return EXIT_FAILURE;
+ }
+
+ while (!terminating) {
+ if (reloading) {
+ reloading = false;
+
+ /* As a separate but related feature, we can also notify the manager
+ * when reloading configuration\&. This allows accurate state\-tracking,
+ * and also automated hook\-in of \*(Aqsystemctl reload\*(Aq without having to
+ * specify manually an ExecReload= line in the unit file\&. */
+
+ r = notify_reloading();
+ if (r < 0) {
+ fprintf(stderr, "Failed to notify reloading to $NOTIFY_SOCKET: %s\en", strerror(\-r));
+ return EXIT_FAILURE;
+ }
+
+ /* Do some reconfiguration work here \&... */
+
+ r = notify_ready();
+ if (r < 0) {
+ fprintf(stderr, "Failed to notify readiness to $NOTIFY_SOCKET: %s\en", strerror(\-r));
+ return EXIT_FAILURE;
+ }
+ }
+
+ /* Do some daemon work here \&... */
+ sleep(5);
+ }
+
+ r = notify_stopping();
+ if (r < 0) {
+ fprintf(stderr, "Failed to report termination to $NOTIFY_SOCKET: %s\en", strerror(\-r));
+ return EXIT_FAILURE;
+ }
+
+ /* Do some shutdown work here \&... */
+
+ return EXIT_SUCCESS;
+}
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.sp
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBPython\fR
+.RS 4
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+#!/usr/bin/env python3
+# SPDX\-License\-Identifier: MIT\-0
+#
+# Implement the systemd notify protocol without external dependencies\&.
+# Supports both readiness notification on startup and on 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/
+
+import errno
+import os
+import signal
+import socket
+import sys
+import time
+
+reloading = False
+terminating = False
+
+def notify(message):
+ if not message:
+ raise ValueError("notify() requires a message")
+
+ socket_path = os\&.environ\&.get("NOTIFY_SOCKET")
+ if not socket_path:
+ return
+
+ if socket_path[0] not in ("/", "@"):
+ raise OSError(errno\&.EAFNOSUPPORT, "Unsupported socket type")
+
+ # Handle abstract socket\&.
+ if socket_path[0] == "@":
+ socket_path = "\e0" + socket_path[1:]
+
+ with socket\&.socket(socket\&.AF_UNIX, socket\&.SOCK_DGRAM | socket\&.SOCK_CLOEXEC) as sock:
+ sock\&.connect(socket_path)
+ sock\&.sendall(message)
+
+def notify_ready():
+ notify(b"READY=1")
+
+def notify_reloading():
+ microsecs = time\&.clock_gettime_ns(time\&.CLOCK_MONOTONIC) // 1000
+ notify(f"RELOADING=1\enMONOTONIC_USEC={microsecs}"\&.encode())
+
+def notify_stopping():
+ notify(b"STOPPING=1")
+
+def reload(signum, frame):
+ global reloading
+ reloading = True
+
+def terminate(signum, frame):
+ global terminating
+ terminating = True
+
+def main():
+ print("Doing initial setup")
+ global reloading, terminating
+
+ # Set up signal handlers\&.
+ print("Setting up signal handlers")
+ signal\&.signal(signal\&.SIGHUP, reload)
+ signal\&.signal(signal\&.SIGINT, terminate)
+ signal\&.signal(signal\&.SIGTERM, terminate)
+
+ # Do any other setup work here\&.
+
+ # Once all setup is done, signal readiness\&.
+ print("Done setting up")
+ notify_ready()
+
+ print("Starting loop")
+ while not terminating:
+ if reloading:
+ print("Reloading")
+ reloading = False
+
+ # Support notifying the manager when reloading configuration\&.
+ # This allows accurate state tracking as well as automatically
+ # enabling \*(Aqsystemctl reload\*(Aq without needing to manually
+ # specify an ExecReload= line in the unit file\&.
+
+ notify_reloading()
+
+ # Do some reconfiguration work here\&.
+
+ print("Done reloading")
+ notify_ready()
+
+ # Do the real work here \&.\&.\&.
+
+ print("Sleeping for five seconds")
+ time\&.sleep(5)
+
+ print("Terminating")
+ notify_stopping()
+
+if __name__ == "__main__":
+ sys\&.stdout\&.reconfigure(line_buffering=True)
+ print("Starting app")
+ main()
+ print("Stopped app")
+.fi
+.if n \{\
+.RE
+.\}
+.RE
.SH "ENVIRONMENT"
.PP
\fI$NOTIFY_SOCKET\fR
@@ -458,8 +800,8 @@ A service could send the following after completing initialization:
.\}
.nf
sd_notifyf(0, "READY=1\en"
- "STATUS=Processing requests\&...\en"
- "MAINPID=%lu",
+ "STATUS=Processing requests\&...\en"
+ "MAINPID=%lu",
(unsigned long) getpid());
.fi
.if n \{\
@@ -475,7 +817,7 @@ A service could send the following shortly before exiting, on failure:
.\}
.nf
sd_notifyf(0, "STATUS=Failed to start up: %s\en"
- "ERRNO=%i",
+ "ERRNO=%i",
strerror_r(errnum, (char[1024]){}, 1024),
errnum);
.fi
@@ -532,13 +874,7 @@ and
were added in version 254\&.
.SH "SEE ALSO"
.PP
-\fBsystemd\fR(1),
-\fBsd-daemon\fR(3),
-\fBsd_listen_fds\fR(3),
-\fBsd_listen_fds_with_names\fR(3),
-\fBsd_watchdog_enabled\fR(3),
-\fBdaemon\fR(7),
-\fBsystemd.service\fR(5)
+\fBsystemd\fR(1), \fBsd-daemon\fR(3), \fBsd_listen_fds\fR(3), \fBsd_listen_fds_with_names\fR(3), \fBsd_watchdog_enabled\fR(3), \fBdaemon\fR(7), \fBsystemd.service\fR(5)
.SH "NOTES"
.IP " 1." 4
File Descriptor Store