diff --git a/man/sd_notify.xml b/man/sd_notify.xml
index 3ba242b90b..a53b1ab33e 100644
--- a/man/sd_notify.xml
+++ b/man/sd_notify.xml
@@ -234,25 +234,26 @@
to send messages with FDSTORE=1, see below.
+
+ FDSTOREREMOVE=1
+
+ Removes file descriptors from the file descriptor store. This field needs to be combined with
+ FDNAME= to specify the name of the file descriptors to remove.
+
+
FDNAME=…
- When used in combination with
- FDSTORE=1, specifies a name for the
- submitted file descriptors. This name is passed to the service
- during activation, and may be queried using
+ When used in combination with FDSTORE=1, specifies a name for the submitted
+ file descriptors. When used with FDSTOREREMOVE=1, specifies the name for the file
+ descriptors to remove. This name is passed to the service during activation, and may be queried using
sd_listen_fds_with_names3. File
- descriptors submitted without this field set, will implicitly
- get the name stored assigned. Note that, if
- multiple file descriptors are submitted at once, the specified
- name will be assigned to all of them. In order to assign
- different names to submitted file descriptors, submit them in
- separate invocations of
- sd_pid_notify_with_fds(). The name may
- consist of any ASCII character, but must not contain control
- characters or :. It may not be longer than
- 255 characters. If a submitted name does not follow these
- restrictions, it is ignored.
+ descriptors submitted without this field set, will implicitly get the name stored
+ assigned. Note that, if multiple file descriptors are submitted at once, the specified name will be assigned to
+ all of them. In order to assign different names to submitted file descriptors, submit them in separate
+ invocations of sd_pid_notify_with_fds(). The name may consist of arbitrary ASCII
+ characters except control characters or :. It may not be longer than 255 characters. If a
+ submitted name does not follow these restrictions, it is ignored.
diff --git a/src/core/service.c b/src/core/service.c
index b25ed49cce..bd187a2753 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -458,6 +458,21 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) {
return 0;
}
+static void service_remove_fd_store(Service *s, const char *name) {
+ ServiceFDStore *fs, *n;
+
+ assert(s);
+ assert(name);
+
+ LIST_FOREACH_SAFE(fd_store, fs, n, s->fd_store) {
+ if (!streq(fs->fdname, name))
+ continue;
+
+ log_unit_debug(UNIT(s), "Got explicit request to remove fd %i (%s), closing.", fs->fd, name);
+ service_fd_store_unlink(fs);
+ }
+}
+
static int service_arm_timer(Service *s, usec_t usec) {
int r;
@@ -3466,7 +3481,19 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
service_reset_watchdog_timeout(s, watchdog_override_usec);
}
- if (strv_find(tags, "FDSTORE=1")) {
+ /* Process FD store messages. Either FDSTOREREMOVE=1 for removal, or FDSTORE=1 for addition. In both cases,
+ * process FDNAME= for picking the file descriptor name to use. Note that FDNAME= is required when removing
+ * fds, but optional when pushing in new fds, for compatibility reasons. */
+ if (strv_find(tags, "FDSTOREREMOVE=1")) {
+ const char *name;
+
+ name = strv_find_startswith(tags, "FDNAME=");
+ if (!name || !fdname_is_valid(name))
+ log_unit_warning(u, "FDSTOREREMOVE=1 requested, but no valid file descriptor name passed, ignoring.");
+ else
+ service_remove_fd_store(s, name);
+
+ } else if (strv_find(tags, "FDSTORE=1")) {
const char *name;
name = strv_find_startswith(tags, "FDNAME=");
@@ -3475,7 +3502,7 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
name = NULL;
}
- service_add_fd_store_set(s, fds, name);
+ (void) service_add_fd_store_set(s, fds, name);
}
/* Notify clients about changed status or main pid */
diff --git a/src/systemd/sd-daemon.h b/src/systemd/sd-daemon.h
index 3fd0cc60e3..9772a05dad 100644
--- a/src/systemd/sd-daemon.h
+++ b/src/systemd/sd-daemon.h
@@ -222,6 +222,15 @@ int sd_is_mq(int fd, const char *path);
invocation. This variable is only supported with
sd_pid_notify_with_fds().
+ FDSTOREREMOVE=1
+ Remove one or more file descriptors from the file
+ descriptor store, identified by the name specified
+ in FDNAME=, see below.
+
+ FDNAME= A name to assign to new file descriptors stored in the
+ file descriptor store, or the name of the file descriptors
+ to remove in case of FDSTOREREMOVE=1.
+
Daemons can choose to send additional variables. However, it is
recommended to prefix variable names not listed above with X_.