mirror of
https://github.com/systemd/systemd
synced 2024-10-15 12:34:37 +00:00
core: when restarting services, don't close fds
We would close all the stored fds in service_release_resources(), which of course broke the whole concept of storing fds over service restart. Fixes #4408.
This commit is contained in:
parent
99bdcdc7fc
commit
f0bfbfac43
|
@ -289,7 +289,17 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
|
|||
free(fs);
|
||||
}
|
||||
|
||||
static void service_release_resources(Unit *u) {
|
||||
static void service_release_fd_store(Service *s) {
|
||||
assert(s);
|
||||
|
||||
log_unit_debug(UNIT(s), "Releasing all stored fds");
|
||||
while (s->fd_store)
|
||||
service_fd_store_unlink(s->fd_store);
|
||||
|
||||
assert(s->n_fd_store == 0);
|
||||
}
|
||||
|
||||
static void service_release_resources(Unit *u, bool inactive) {
|
||||
Service *s = SERVICE(u);
|
||||
|
||||
assert(s);
|
||||
|
@ -297,16 +307,14 @@ static void service_release_resources(Unit *u) {
|
|||
if (!s->fd_store && s->stdin_fd < 0 && s->stdout_fd < 0 && s->stderr_fd < 0)
|
||||
return;
|
||||
|
||||
log_unit_debug(u, "Releasing all resources.");
|
||||
log_unit_debug(u, "Releasing resources.");
|
||||
|
||||
s->stdin_fd = safe_close(s->stdin_fd);
|
||||
s->stdout_fd = safe_close(s->stdout_fd);
|
||||
s->stderr_fd = safe_close(s->stderr_fd);
|
||||
|
||||
while (s->fd_store)
|
||||
service_fd_store_unlink(s->fd_store);
|
||||
|
||||
assert(s->n_fd_store == 0);
|
||||
if (inactive)
|
||||
service_release_fd_store(s);
|
||||
}
|
||||
|
||||
static void service_done(Unit *u) {
|
||||
|
@ -350,7 +358,7 @@ static void service_done(Unit *u) {
|
|||
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
|
||||
service_release_resources(u);
|
||||
service_release_resources(u, true);
|
||||
}
|
||||
|
||||
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) {
|
||||
|
|
|
@ -302,6 +302,7 @@ int unit_set_description(Unit *u, const char *description) {
|
|||
|
||||
bool unit_check_gc(Unit *u) {
|
||||
UnitActiveState state;
|
||||
bool inactive;
|
||||
assert(u);
|
||||
|
||||
if (u->job)
|
||||
|
@ -311,16 +312,17 @@ bool unit_check_gc(Unit *u) {
|
|||
return true;
|
||||
|
||||
state = unit_active_state(u);
|
||||
inactive = state == UNIT_INACTIVE;
|
||||
|
||||
/* If the unit is inactive and failed and no job is queued for
|
||||
* it, then release its runtime resources */
|
||||
if (UNIT_IS_INACTIVE_OR_FAILED(state) &&
|
||||
UNIT_VTABLE(u)->release_resources)
|
||||
UNIT_VTABLE(u)->release_resources(u);
|
||||
UNIT_VTABLE(u)->release_resources(u, inactive);
|
||||
|
||||
/* But we keep the unit object around for longer when it is
|
||||
* referenced or configured to not be gc'ed */
|
||||
if (state != UNIT_INACTIVE)
|
||||
if (!inactive)
|
||||
return true;
|
||||
|
||||
if (u->no_gc)
|
||||
|
|
|
@ -372,7 +372,7 @@ struct UnitVTable {
|
|||
|
||||
/* When the unit is not running and no job for it queued we
|
||||
* shall release its runtime resources */
|
||||
void (*release_resources)(Unit *u);
|
||||
void (*release_resources)(Unit *u, bool inactive);
|
||||
|
||||
/* Invoked on every child that died */
|
||||
void (*sigchld_event)(Unit *u, pid_t pid, int code, int status);
|
||||
|
|
Loading…
Reference in a new issue