|
|
55853a |
From 7c39b498d6ea21b1c6f4d26b74c064ef2b507706 Mon Sep 17 00:00:00 2001
|
|
|
55853a |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
55853a |
Date: Mon, 13 Nov 2017 15:08:49 +0100
|
|
|
55853a |
Subject: [PATCH] unit: rework a bit how we keep the service fdstore from being
|
|
|
55853a |
destroyed during service restart
|
|
|
55853a |
|
|
|
55853a |
When preparing for a restart we quickly go through the DEAD/INACTIVE
|
|
|
55853a |
service state before entering AUTO_RESTART. When doing this, we need to
|
|
|
55853a |
make sure we don't destroy the FD store. Previously this was done by
|
|
|
55853a |
checking the failure state of the unit, and keeping the FD store around
|
|
|
55853a |
when the unit failed, under the assumption that the restart logic will
|
|
|
55853a |
then get into action.
|
|
|
55853a |
|
|
|
55853a |
This is not entirely correct howver, as there might be failure states
|
|
|
55853a |
that will no result in restarts.
|
|
|
55853a |
|
|
|
55853a |
With this commit we slightly alter the logic: a ref counter for the fd
|
|
|
55853a |
store is added, that is increased right before we handle the restart
|
|
|
55853a |
logic, and decreased again right-after.
|
|
|
55853a |
|
|
|
55853a |
This should ensure that the fdstore lives exactly as long as it needs.
|
|
|
55853a |
|
|
|
55853a |
Follow-up for f0bfbfac43b7faa68ef1bb2ad659c191b9ec85d2.
|
|
|
55853a |
|
|
|
55853a |
(cherry picked from commit 7eb2a8a1259043e107ebec94e30ed160a93f40a7)
|
|
|
55853a |
(cherry picked from commit e2636bde0f07319d0d35262dac6ff2638ba4e598)
|
|
|
55853a |
(cherry picked from commit 20b18b7b9aac2532215dba4d56f19989a5fca9f0)
|
|
|
55853a |
Related: #1798162
|
|
|
55853a |
---
|
|
|
55853a |
src/core/service.c | 23 ++++++++++++++++++-----
|
|
|
55853a |
src/core/service.h | 1 +
|
|
|
55853a |
src/core/unit.c | 12 ++++--------
|
|
|
55853a |
src/core/unit.h | 5 ++---
|
|
|
55853a |
4 files changed, 25 insertions(+), 16 deletions(-)
|
|
|
55853a |
|
|
|
55853a |
diff --git a/src/core/service.c b/src/core/service.c
|
|
|
55853a |
index ad45a38270..283c2968ea 100644
|
|
|
55853a |
--- a/src/core/service.c
|
|
|
55853a |
+++ b/src/core/service.c
|
|
|
55853a |
@@ -265,6 +265,9 @@ static void service_fd_store_unlink(ServiceFDStore *fs) {
|
|
|
55853a |
static void service_release_fd_store(Service *s) {
|
|
|
55853a |
assert(s);
|
|
|
55853a |
|
|
|
55853a |
+ if (s->n_keep_fd_store > 0)
|
|
|
55853a |
+ return;
|
|
|
55853a |
+
|
|
|
55853a |
log_unit_debug(UNIT(s)->id, "Releasing all stored fds");
|
|
|
55853a |
while (s->fd_store)
|
|
|
55853a |
service_fd_store_unlink(s->fd_store);
|
|
|
55853a |
@@ -272,7 +275,7 @@ static void service_release_fd_store(Service *s) {
|
|
|
55853a |
assert(s->n_fd_store == 0);
|
|
|
55853a |
}
|
|
|
55853a |
|
|
|
55853a |
-static void service_release_resources(Unit *u, bool inactive) {
|
|
|
55853a |
+static void service_release_resources(Unit *u) {
|
|
|
55853a |
Service *s = SERVICE(u);
|
|
|
55853a |
|
|
|
55853a |
assert(s);
|
|
|
55853a |
@@ -282,8 +285,7 @@ static void service_release_resources(Unit *u, bool inactive) {
|
|
|
55853a |
|
|
|
55853a |
log_unit_debug(u->id, "Releasing resources.");
|
|
|
55853a |
|
|
|
55853a |
- if (inactive)
|
|
|
55853a |
- service_release_fd_store(s);
|
|
|
55853a |
+ service_release_fd_store(s);
|
|
|
55853a |
}
|
|
|
55853a |
|
|
|
55853a |
static void service_done(Unit *u) {
|
|
|
55853a |
@@ -331,7 +333,7 @@ static void service_done(Unit *u) {
|
|
|
55853a |
|
|
|
55853a |
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
|
|
55853a |
|
|
|
55853a |
- service_release_resources(u, true);
|
|
|
55853a |
+ service_release_resources(u);
|
|
|
55853a |
}
|
|
|
55853a |
|
|
|
55853a |
static int on_fd_store_io(sd_event_source *e, int fd, uint32_t revents, void *userdata) {
|
|
|
55853a |
@@ -1354,6 +1356,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
|
|
55853a |
if (f != SERVICE_SUCCESS)
|
|
|
55853a |
s->result = f;
|
|
|
55853a |
|
|
|
55853a |
+ /* Make sure service_release_resources() doesn't destroy our FD store, while we are changing through
|
|
|
55853a |
+ * SERVICE_FAILED/SERVICE_DEAD before entering into SERVICE_AUTO_RESTART. */
|
|
|
55853a |
+ s->n_keep_fd_store++;
|
|
|
55853a |
+
|
|
|
55853a |
service_set_state(s, s->result != SERVICE_SUCCESS ? SERVICE_FAILED : SERVICE_DEAD);
|
|
|
55853a |
|
|
|
55853a |
if (s->result != SERVICE_SUCCESS) {
|
|
|
55853a |
@@ -1375,12 +1381,19 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
|
|
|
55853a |
(!IN_SET(s->main_exec_status.code, CLD_KILLED, CLD_DUMPED) || !set_contains(s->restart_prevent_status.signal, INT_TO_PTR(s->main_exec_status.status)))) {
|
|
|
55853a |
|
|
|
55853a |
r = service_arm_timer(s, s->restart_usec);
|
|
|
55853a |
- if (r < 0)
|
|
|
55853a |
+ if (r < 0) {
|
|
|
55853a |
+ s->n_keep_fd_store--;
|
|
|
55853a |
goto fail;
|
|
|
55853a |
+ }
|
|
|
55853a |
|
|
|
55853a |
service_set_state(s, SERVICE_AUTO_RESTART);
|
|
|
55853a |
}
|
|
|
55853a |
|
|
|
55853a |
+ /* The new state is in effect, let's decrease the fd store ref counter again. Let's also readd us to the GC
|
|
|
55853a |
+ * queue, so that the fd store is possibly gc'ed again */
|
|
|
55853a |
+ s->n_keep_fd_store--;
|
|
|
55853a |
+ unit_add_to_gc_queue(UNIT(s));
|
|
|
55853a |
+
|
|
|
55853a |
s->forbid_restart = false;
|
|
|
55853a |
|
|
|
55853a |
/* We want fresh tmpdirs in case service is started again immediately */
|
|
|
55853a |
diff --git a/src/core/service.h b/src/core/service.h
|
|
|
55853a |
index e0547a464e..81b17db652 100644
|
|
|
55853a |
--- a/src/core/service.h
|
|
|
55853a |
+++ b/src/core/service.h
|
|
|
55853a |
@@ -214,6 +214,7 @@ struct Service {
|
|
|
55853a |
ServiceFDStore *fd_store;
|
|
|
55853a |
unsigned n_fd_store;
|
|
|
55853a |
unsigned n_fd_store_max;
|
|
|
55853a |
+ unsigned n_keep_fd_store;
|
|
|
55853a |
};
|
|
|
55853a |
|
|
|
55853a |
extern const UnitVTable service_vtable;
|
|
|
55853a |
diff --git a/src/core/unit.c b/src/core/unit.c
|
|
|
55853a |
index 33e0b7126b..e74c6bc2cc 100644
|
|
|
55853a |
--- a/src/core/unit.c
|
|
|
55853a |
+++ b/src/core/unit.c
|
|
|
55853a |
@@ -284,7 +284,6 @@ int unit_set_description(Unit *u, const char *description) {
|
|
|
55853a |
|
|
|
55853a |
bool unit_may_gc(Unit *u) {
|
|
|
55853a |
UnitActiveState state;
|
|
|
55853a |
- bool inactive;
|
|
|
55853a |
assert(u);
|
|
|
55853a |
|
|
|
55853a |
/* Checks whether the unit is ready to be unloaded for garbage collection.
|
|
|
55853a |
@@ -302,17 +301,14 @@ bool unit_may_gc(Unit *u) {
|
|
|
55853a |
return false;
|
|
|
55853a |
|
|
|
55853a |
state = unit_active_state(u);
|
|
|
55853a |
- inactive = state == UNIT_INACTIVE;
|
|
|
55853a |
|
|
|
55853a |
- /* If the unit is inactive and failed and no job is queued for
|
|
|
55853a |
- * it, then release its runtime resources */
|
|
|
55853a |
+ /* If the unit is inactive and failed and no job is queued for it, then release its runtime resources */
|
|
|
55853a |
if (UNIT_IS_INACTIVE_OR_FAILED(state) &&
|
|
|
55853a |
UNIT_VTABLE(u)->release_resources)
|
|
|
55853a |
- UNIT_VTABLE(u)->release_resources(u, inactive);
|
|
|
55853a |
+ UNIT_VTABLE(u)->release_resources(u);
|
|
|
55853a |
|
|
|
55853a |
- /* But we keep the unit object around for longer when it is
|
|
|
55853a |
- * referenced or configured to not be gc'ed */
|
|
|
55853a |
- if (!inactive)
|
|
|
55853a |
+ /* But we keep the unit object around for longer when it is referenced or configured to not be gc'ed */
|
|
|
55853a |
+ if (state != UNIT_INACTIVE)
|
|
|
55853a |
return false;
|
|
|
55853a |
|
|
|
55853a |
if (UNIT_VTABLE(u)->no_gc)
|
|
|
55853a |
diff --git a/src/core/unit.h b/src/core/unit.h
|
|
|
55853a |
index 97a63f0f8b..61ff59e8c7 100644
|
|
|
55853a |
--- a/src/core/unit.h
|
|
|
55853a |
+++ b/src/core/unit.h
|
|
|
55853a |
@@ -357,9 +357,8 @@ struct UnitVTable {
|
|
|
55853a |
* even though nothing references it and it isn't active in any way. */
|
|
|
55853a |
bool (*may_gc)(Unit *u);
|
|
|
55853a |
|
|
|
55853a |
- /* When the unit is not running and no job for it queued we
|
|
|
55853a |
- * shall release its runtime resources */
|
|
|
55853a |
- void (*release_resources)(Unit *u, bool inactive);
|
|
|
55853a |
+ /* When the unit is not running and no job for it queued we shall release its runtime resources */
|
|
|
55853a |
+ void (*release_resources)(Unit *u);
|
|
|
55853a |
|
|
|
55853a |
/* Return true when this unit is suitable for snapshotting */
|
|
|
55853a |
bool (*check_snapshot)(Unit *u);
|