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_.