diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index cb07add95eb..707e3515118 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -238,25 +238,29 @@
FDSTORE=1
- Stores additional file descriptors in the service manager. File descriptors sent this way will
- be maintained per-service by the service manager and will later be handed back using the usual file descriptor
- passing logic at the next invocation of the service (e.g. when it is restarted), see
- sd_listen_fds3. This is
- useful for implementing services that can restart after an explicit request or a crash without losing
- state. Any open sockets and other file descriptors which should not be closed during the restart may be stored
- this way. Application state can either be serialized to a file in /run/, or better, stored
- in a memfd_create2 memory
- file descriptor. Note that the service manager will accept messages for a service only if its
+ Stores additional file descriptors in the service manager. File descriptors sent this
+ way will be maintained per-service by the service manager and will later be handed back using the
+ usual file descriptor passing logic at the next invocation of the service (e.g. when it is
+ restarted), see
+ sd_listen_fds3.
+ This is useful for implementing services that can restart after an explicit request or a crash
+ without losing state. Any open sockets and other file descriptors which should not be closed during
+ the restart may be stored this way. Application state can either be serialized to a file in
+ /run/, or better, stored in a
+ memfd_create2
+ memory file descriptor. Note that the service manager will accept messages for a service only if its
FileDescriptorStoreMax= setting is non-zero (defaults to zero, see
systemd.service5). If
FDPOLL=0 is not set and the file descriptors sent are pollable (see
- epoll_ctl2), then any
- EPOLLHUP or EPOLLERR event seen on them will result in their
- automatic removal from the store. Multiple arrays of file descriptors may be sent in separate messages, in
- which case the arrays are combined. Note that the service manager removes duplicate (pointing to the same
- object) file descriptors before passing them to the service. When a service is stopped, its file descriptor
- store is discarded and all file descriptors in it are closed. Use sd_pid_notify_with_fds()
- to send messages with FDSTORE=1, see below.
+ epoll_ctl2), then
+ any EPOLLHUP or EPOLLERR event seen on them will result in
+ their automatic removal from the store. Multiple arrays of file descriptors may be sent in separate
+ messages, in which case the arrays are combined. Note that the service manager removes duplicate
+ (pointing to the same object) file descriptors before passing them to the service. When a service is
+ stopped, its file descriptor store is discarded and all file descriptors in it are closed. Use
+ sd_pid_notify_with_fds() to send messages with FDSTORE=1, see
+ below. The service manager will set the $FDSTORE environment variable for services
+ that have the file descriptor store enabled.
@@ -348,19 +352,14 @@
sd_notify() and
sd_notifyf().
- sd_pid_notify_with_fds() is similar to
- sd_pid_notify() but takes an additional array
- of file descriptors. These file descriptors are sent along the
- notification message to the service manager. This is particularly
- useful for sending FDSTORE=1 messages, as
- described above. The additional arguments are a pointer to the
- file descriptor array plus the number of file descriptors in the
- array. If the number of file descriptors is passed as 0, the call
- is fully equivalent to sd_pid_notify(), i.e.
- no file descriptors are passed. Note that sending file descriptors
- to the service manager on messages that do not expect them (i.e.
- without FDSTORE=1) they are immediately closed
- on reception.
+ sd_pid_notify_with_fds() is similar to sd_pid_notify()
+ but takes an additional array of file descriptors. These file descriptors are sent along the notification
+ message to the service manager. This is particularly useful for sending FDSTORE=1
+ messages, as described above. The additional arguments are a pointer to the file descriptor array plus
+ the number of file descriptors in the array. If the number of file descriptors is passed as 0, the call
+ is fully equivalent to sd_pid_notify(), i.e. no file descriptors are passed. Note
+ that file descriptors sent to the service manager on a message without FDSTORE=1 are
+ immediately closed on reception.
sd_notify_barrier() allows the caller to
synchronize against reception of previously sent notification messages
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
index 17be33c56a2..3a4af9cabe1 100644
--- a/man/systemd.exec.xml
+++ b/man/systemd.exec.xml
@@ -3476,8 +3476,7 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
$NOTIFY_SOCKET
- The socket
- sd_notify() talks to. See
+ The socket sd_notify() talks to. See
sd_notify3.
@@ -3799,6 +3798,19 @@ StandardInputData=V2XigLJyZSBubyBzdHJhbmdlcnMgdG8gbG92ZQpZb3Uga25vdyB0aGUgcnVsZX
convey.
+
+ $FDSTORE
+
+ If the file descriptor store is enabled for a service
+ (i.e. FileDescriptorStoreMax= is set to a non-zero value, see
+ systemd.service5
+ for details), this environment variable will be set to the maximum number of permitted entries, as
+ per the setting. Applications may check this environment variable before sending file descriptors
+ to the service manager via sd_pid_notify_with_fds() (see
+ sd_notify3 for
+ details).
+
+
For system services, when PAMName= is enabled and pam_systemd is part
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index f64a8e538ff..1b116b8372a 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -1089,7 +1089,12 @@
allow unprivileged clients to query the list of currently open file descriptors of a
service. Sensitive data may hence be safely placed inside the referenced files, but should not be
attached to the metadata (e.g. included in filenames) of the stored file
- descriptors.
+ descriptors.
+
+ If this option is set to a non-zero value the $FDSTORE environment variable
+ will be set for processes invoked for this service. See
+ systemd.exec5 for
+ details.
diff --git a/src/core/service.c b/src/core/service.c
index 48229f96ee3..650741cc7ce 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1677,7 +1677,7 @@ static int service_spawn_internal(
if (r < 0)
return r;
- our_env = new0(char*, 12);
+ our_env = new0(char*, 13);
if (!our_env)
return -ENOMEM;
@@ -1686,6 +1686,10 @@ static int service_spawn_internal(
return -ENOMEM;
exec_params.notify_socket = UNIT(s)->manager->notify_socket;
+
+ if (s->n_fd_store_max > 0)
+ if (asprintf(our_env + n_env++, "FDSTORE=%u", s->n_fd_store_max) < 0)
+ return -ENOMEM;
}
if (s->main_pid > 0)
diff --git a/test/units/testsuite-80.sh b/test/units/testsuite-80.sh
index 0072133cd4e..15ea36bf88d 100755
--- a/test/units/testsuite-80.sh
+++ b/test/units/testsuite-80.sh
@@ -53,6 +53,7 @@ cat >> "$MYSCRIPT" <<'EOF'
#!/usr/bin/env bash
set -eux
set -o pipefail
+test "$FDSTORE" -eq 7
N="/tmp/$RANDOM"
echo $RANDOM > "$N"
systemd-notify --fd=4 --fdname=quux --pid=parent 4< "$N"