core: add a new sd_notify() message for removing fds from the FD store again

Currenly the only way to remove fds from the fdstore is to fully
stop the service, or to somehow trigger POLLERR/POLLHUP on the fd, in
which case systemd will remove the fd automatically.

Let's add another way: a new message that can be sent to remove fds
explicitly, given their name.
This commit is contained in:
Lennart Poettering 2017-11-13 18:26:04 +01:00
parent 8d1ab18a46
commit e78ee06de1
3 changed files with 54 additions and 17 deletions

View File

@ -234,25 +234,26 @@
to send messages with <literal>FDSTORE=1</literal>, see below.</para></listitem>
</varlistentry>
<varlistentry>
<term>FDSTOREREMOVE=1</term>
<listitem><para>Removes file descriptors from the file descriptor store. This field needs to be combined with
<varname>FDNAME=</varname> to specify the name of the file descriptors to remove.</para></listitem>
</varlistentry>
<varlistentry>
<term>FDNAME=…</term>
<listitem><para>When used in combination with
<varname>FDSTORE=1</varname>, specifies a name for the
submitted file descriptors. This name is passed to the service
during activation, and may be queried using
<listitem><para>When used in combination with <varname>FDSTORE=1</varname>, specifies a name for the submitted
file descriptors. When used with <varname>FDSTOREREMOVE=1</varname>, specifies the name for the file
descriptors to remove. This name is passed to the service during activation, and may be queried using
<citerefentry><refentrytitle>sd_listen_fds_with_names</refentrytitle><manvolnum>3</manvolnum></citerefentry>. File
descriptors submitted without this field set, will implicitly
get the name <literal>stored</literal> 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
<function>sd_pid_notify_with_fds()</function>. The name may
consist of any ASCII character, but must not contain control
characters or <literal>:</literal>. It may not be longer than
255 characters. If a submitted name does not follow these
restrictions, it is ignored.</para></listitem>
descriptors submitted without this field set, will implicitly get the name <literal>stored</literal>
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 <function>sd_pid_notify_with_fds()</function>. The name may consist of arbitrary ASCII
characters except control characters or <literal>:</literal>. It may not be longer than 255 characters. If a
submitted name does not follow these restrictions, it is ignored.</para></listitem>
</varlistentry>
</variablelist>

View File

@ -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 */

View File

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