diff options
author | Kenny Levinsen <kl@kl.wtf> | 2020-04-08 20:19:30 +0200 |
---|---|---|
committer | Kenny Levinsen <kl@kl.wtf> | 2020-04-30 19:42:26 +0200 |
commit | cb5a46b84504006196e4415266c1a6414c07c9b3 (patch) | |
tree | aef16cbee4a79b4c5f570fa21a8f1f72e493811c | |
parent | 9dcd43b14927fe6f9182a252213dbf182d9d8e01 (diff) | |
download | systemd-cb5a46b84504006196e4415266c1a6414c07c9b3.tar.gz |
core: Add optional FDPOLL=0 argument to fdstore
A service can specify FDSTORE=1 FDPOLL=0 to request that PID1 does not
poll the fd to remove them on error. If set, fds will only be removed on
FDSTOREREMOVE=1 or when the service is done.
Fixes: #12086
-rw-r--r-- | man/sd_notify.xml | 14 | ||||
-rw-r--r-- | src/core/service.c | 26 |
2 files changed, 26 insertions, 14 deletions
diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 3046ca88ee..0157ce864a 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -219,8 +219,8 @@ in a <citerefentry><refentrytitle>memfd_create</refentrytitle><manvolnum>2</manvolnum></citerefentry> memory file descriptor. Note that the service manager will accept messages for a service only if its <varname>FileDescriptorStoreMax=</varname> setting is non-zero (defaults to zero, see - <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If file - descriptors sent are pollable (see + <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>). If + <varname>FDPOLL=0</varname> is not set and the file descriptors sent are pollable (see <citerefentry><refentrytitle>epoll_ctl</refentrytitle><manvolnum>2</manvolnum></citerefentry>), then any <constant>EPOLLHUP</constant> or <constant>EPOLLERR</constant> 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 @@ -251,6 +251,16 @@ submitted name does not follow these restrictions, it is ignored.</para></listitem> </varlistentry> + <varlistentry> + <term>FDPOLL=0</term> + + <listitem><para>When used in combination with <varname>FDSTORE=1</varname>, disables polling of the stored + file descriptors regardless of whether or not they are pollable. As this option disables automatic cleanup + of the stored file descriptors on EPOLLERR and EPOLLHUP, care must be taken to ensure proper manual cleanup. + Use of this option is not generally recommended except for when automatic cleanup has unwanted behavior such + as prematurely discarding file descriptors from the store.</para></listitem> + </varlistentry> + </variablelist> <para>It is recommended to prefix variable names that are not diff --git a/src/core/service.c b/src/core/service.c index 7d5928e455..cc8b44f1c8 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -423,7 +423,7 @@ static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *us return 0; } -static int service_add_fd_store(Service *s, int fd, const char *name) { +static int service_add_fd_store(Service *s, int fd, const char *name, bool do_poll) { ServiceFDStore *fs; int r; @@ -459,13 +459,15 @@ static int service_add_fd_store(Service *s, int fd, const char *name) { return -ENOMEM; } - r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs); - if (r < 0 && r != -EPERM) { /* EPERM indicates fds that aren't pollable, which is OK */ - free(fs->fdname); - free(fs); - return r; - } else if (r >= 0) - (void) sd_event_source_set_description(fs->event_source, "service-fd-store"); + if (do_poll) { + r = sd_event_add_io(UNIT(s)->manager->event, &fs->event_source, fd, 0, on_fd_store_io, fs); + if (r < 0 && r != -EPERM) { /* EPERM indicates fds that aren't pollable, which is OK */ + free(fs->fdname); + free(fs); + return r; + } 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++; @@ -473,7 +475,7 @@ static int service_add_fd_store(Service *s, int fd, const char *name) { return 1; /* fd newly stored */ } -static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { +static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name, bool do_poll) { int r; assert(s); @@ -485,7 +487,7 @@ static int service_add_fd_store_set(Service *s, FDSet *fds, const char *name) { if (fd < 0) break; - r = service_add_fd_store(s, fd, name); + r = service_add_fd_store(s, fd, name, do_poll); if (r == -EXFULL) return log_unit_warning_errno(UNIT(s), r, "Cannot store more fds than FileDescriptorStoreMax=%u, closing remaining.", @@ -2961,7 +2963,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, fdn += strspn(fdn, WHITESPACE); (void) cunescape(fdn, 0, &t); - r = service_add_fd_store(s, fd, t); + r = service_add_fd_store(s, fd, t, true); if (r < 0) log_unit_error_errno(u, r, "Failed to add fd to store: %m"); else @@ -4068,7 +4070,7 @@ static void service_notify_message( name = NULL; } - (void) service_add_fd_store_set(s, fds, name); + (void) service_add_fd_store_set(s, fds, name, !strv_contains(tags, "FDPOLL=0")); } /* Notify clients about changed status or main pid */ |