diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index 4dcefc4baf..e8ddea2f5f 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -205,25 +205,24 @@
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 be passed again using the usual file descriptor passing logic on the next
- invocation of the service, see
- sd_listen_fds3.
- This is useful for implementing service restart schemes where services serialize
- their state to /run, push their file descriptors to the
- system manager, and are then restarted, retrieving their state again via socket
- passing and /run. Note that the service manager will accept
- messages for a service only if FileDescriptorStoreMax= is set
- to non-zero for it (defaults to zero, see
- systemd.service5).
- File descriptors must be pollable, see
- epoll_ctl2.
- 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
- file descriptors before passing them to the service. Use
- sd_pid_notify_with_fds() to send messages with
- FDSTORE=1, see below.
+ 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, 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 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. Use sd_pid_notify_with_fds()
+ to send messages with FDSTORE=1, see below.
@@ -312,13 +311,14 @@
Return Value
- On failure, these calls return a negative errno-style error
- code. If $NOTIFY_SOCKET was not set and hence
- no status data could be sent, 0 is returned. If the status was
- sent, these functions return with a positive return value. In
- order to support both, init systems that implement this scheme and
- those which do not, it is generally recommended to ignore the
- return value of this call.
+ On failure, these calls return a negative errno-style error code. If $NOTIFY_SOCKET was
+ not set and hence no status message could be sent, 0 is returned. If the status was sent, these functions return a
+ positive value. In order to support both service managers that implement this scheme and those which do not, it is
+ generally recommended to ignore the return value of this call. Note that the return value simply indicates whether
+ the notification message was enqueued properly, it does not reflect whether the message could be processed
+ successfully. Specifically, no error is returned when a file descriptor is attempted to be stored using
+ FDSTORE=1 but the service is not actually configured to permit storing of file descriptors (see
+ above).
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 95c16fded7..1faac0f762 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -853,21 +853,18 @@
FileDescriptorStoreMax=
- Configure how many file descriptors may be
- stored in the service manager for the service using
+ Configure how many file descriptors may be stored in the service manager for the service using
sd_pid_notify_with_fds3's
- FDSTORE=1 messages. This is useful for
- implementing service restart schemes where the state is
- serialized to /run and the file
- descriptors passed to the service manager, to allow restarts
- without losing state. Defaults to 0, i.e. no file descriptors
- may be stored in the service manager. All file
- descriptors passed to the service manager from a specific
- service are passed back to the service's main process on the
- next service restart. Any file descriptors passed to the
- service manager are automatically closed when POLLHUP or
- POLLERR is seen on them, or when the service is fully stopped
- and no job is queued or being executed for it.
+ FDSTORE=1 messages. 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. Defaults to 0, i.e. no file descriptors may be stored in the service manager. All file descriptors
+ passed to the service manager from a specific service are passed back to the service's main process on the next
+ service restart. Any file descriptors passed to the service manager are automatically closed when
+ POLLHUP or POLLERR is seen on them, or when the service is fully
+ stopped and no job is queued or being executed for it.
diff --git a/src/core/service.c b/src/core/service.c
index df7f1f3053..e1f02ccde1 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -413,13 +413,12 @@ static int service_add_fd_store(Service *s, int fd, const char *name) {
}
r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs);
- if (r < 0) {
+ if (r < 0 && r != -EPERM) { /* EPERM indicates fds that aren't pollable, which is OK */
free(fs->fdname);
free(fs);
return r;
- }
-
- (void) sd_event_source_set_description(fs->event_source, "service-fd-store");
+ } else if (r >= 0)
+ (void) sd_event_source_set_description(fs->event_source, "service-fd-store");
LIST_PREPEND(fd_store, s->fd_store, fs);
s->n_fd_store++;