Michal Schmidt 99043c
From b8eb35a32344948ab82138e8ecee471479ea0959 Mon Sep 17 00:00:00 2001
Michal Schmidt 99043c
From: Lennart Poettering <lennart@poettering.net>
Michal Schmidt 99043c
Date: Thu, 24 May 2012 02:22:35 +0200
Michal Schmidt 99043c
Subject: [PATCH] service: for Type=idle units consider START_PRE, START,
Michal Schmidt 99043c
 START_POST all as ACTIVE
Michal Schmidt 99043c
Michal Schmidt 99043c
We want to avoid a deadlock when a service has ExecStartPre= programs
Michal Schmidt 99043c
that wait for the job queue to run empty because of Type=idle, but which
Michal Schmidt 99043c
themselves keep the queue non-empty because START_PRE was considered
Michal Schmidt 99043c
ACTIVATING and hence the job not complete. With this patch we alter the
Michal Schmidt 99043c
state translation table so that it is impossible ever to wait for
Michal Schmidt 99043c
Type=idle unit, hence removing the deadlock.
Michal Schmidt 99043c
(cherry picked from commit e056b01d8acea7fc06d52ef91d227d744faf5259)
Michal Schmidt 99043c
---
Michal Schmidt 99043c
 src/core/execute.c |    2 +-
Michal Schmidt 99043c
 src/core/service.c |   31 +++++++++++++++++++++++++++++--
Michal Schmidt 99043c
 2 files changed, 30 insertions(+), 3 deletions(-)
Michal Schmidt 99043c
Michal Schmidt 99043c
diff --git a/src/core/execute.c b/src/core/execute.c
Michal Schmidt 99043c
index 67b792b..a2ef77c 100644
Michal Schmidt 99043c
--- a/src/core/execute.c
Michal Schmidt 99043c
+++ b/src/core/execute.c
Michal Schmidt 99043c
@@ -61,7 +61,7 @@
Michal Schmidt 99043c
 #include "loopback-setup.h"
Michal Schmidt 99043c
 #include "path-util.h"
Michal Schmidt 99043c
 
Michal Schmidt 99043c
-#define IDLE_TIMEOUT_USEC (1*USEC_PER_SEC)
Michal Schmidt 99043c
+#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
Michal Schmidt 99043c
 
Michal Schmidt 99043c
 /* This assumes there is a 'tty' group */
Michal Schmidt 99043c
 #define TTY_MODE 0620
Michal Schmidt 99043c
diff --git a/src/core/service.c b/src/core/service.c
Michal Schmidt 99043c
index 3abb729..53b0847 100644
Michal Schmidt 99043c
--- a/src/core/service.c
Michal Schmidt 99043c
+++ b/src/core/service.c
Michal Schmidt 99043c
@@ -108,6 +108,26 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = {
Michal Schmidt 99043c
         [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
Michal Schmidt 99043c
 };
Michal Schmidt 99043c
 
Michal Schmidt 99043c
+/* For Type=idle we never want to delay any other jobs, hence we
Michal Schmidt 99043c
+ * consider idle jobs active as soon as we start working on them */
Michal Schmidt 99043c
+static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = {
Michal Schmidt 99043c
+        [SERVICE_DEAD] = UNIT_INACTIVE,
Michal Schmidt 99043c
+        [SERVICE_START_PRE] = UNIT_ACTIVE,
Michal Schmidt 99043c
+        [SERVICE_START] = UNIT_ACTIVE,
Michal Schmidt 99043c
+        [SERVICE_START_POST] = UNIT_ACTIVE,
Michal Schmidt 99043c
+        [SERVICE_RUNNING] = UNIT_ACTIVE,
Michal Schmidt 99043c
+        [SERVICE_EXITED] = UNIT_ACTIVE,
Michal Schmidt 99043c
+        [SERVICE_RELOAD] = UNIT_RELOADING,
Michal Schmidt 99043c
+        [SERVICE_STOP] = UNIT_DEACTIVATING,
Michal Schmidt 99043c
+        [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING,
Michal Schmidt 99043c
+        [SERVICE_STOP_SIGKILL] = UNIT_DEACTIVATING,
Michal Schmidt 99043c
+        [SERVICE_STOP_POST] = UNIT_DEACTIVATING,
Michal Schmidt 99043c
+        [SERVICE_FINAL_SIGTERM] = UNIT_DEACTIVATING,
Michal Schmidt 99043c
+        [SERVICE_FINAL_SIGKILL] = UNIT_DEACTIVATING,
Michal Schmidt 99043c
+        [SERVICE_FAILED] = UNIT_FAILED,
Michal Schmidt 99043c
+        [SERVICE_AUTO_RESTART] = UNIT_ACTIVATING
Michal Schmidt 99043c
+};
Michal Schmidt 99043c
+
Michal Schmidt 99043c
 static void service_init(Unit *u) {
Michal Schmidt 99043c
         Service *s = SERVICE(u);
Michal Schmidt 99043c
         int i;
Michal Schmidt 99043c
@@ -1469,8 +1489,11 @@ static void service_notify_sockets_dead(Service *s, bool failed_permanent) {
Michal Schmidt 99043c
 
Michal Schmidt 99043c
 static void service_set_state(Service *s, ServiceState state) {
Michal Schmidt 99043c
         ServiceState old_state;
Michal Schmidt 99043c
+        const UnitActiveState *table;
Michal Schmidt 99043c
         assert(s);
Michal Schmidt 99043c
 
Michal Schmidt 99043c
+        table = s->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
Michal Schmidt 99043c
+
Michal Schmidt 99043c
         old_state = s->state;
Michal Schmidt 99043c
         s->state = state;
Michal Schmidt 99043c
 
Michal Schmidt 99043c
@@ -1553,7 +1576,7 @@ static void service_set_state(Service *s, ServiceState state) {
Michal Schmidt 99043c
         if (old_state != state)
Michal Schmidt 99043c
                 log_debug("%s changed %s -> %s", UNIT(s)->id, service_state_to_string(old_state), service_state_to_string(state));
Michal Schmidt 99043c
 
Michal Schmidt 99043c
-        unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], s->reload_result == SERVICE_SUCCESS);
Michal Schmidt 99043c
+        unit_notify(UNIT(s), table[old_state], table[state], s->reload_result == SERVICE_SUCCESS);
Michal Schmidt 99043c
         s->reload_result = SERVICE_SUCCESS;
Michal Schmidt 99043c
 }
Michal Schmidt 99043c
 
Michal Schmidt 99043c
@@ -2692,9 +2715,13 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
Michal Schmidt 99043c
 }
Michal Schmidt 99043c
 
Michal Schmidt 99043c
 static UnitActiveState service_active_state(Unit *u) {
Michal Schmidt 99043c
+        const UnitActiveState *table;
Michal Schmidt 99043c
+
Michal Schmidt 99043c
         assert(u);
Michal Schmidt 99043c
 
Michal Schmidt 99043c
-        return state_translation_table[SERVICE(u)->state];
Michal Schmidt 99043c
+        table = SERVICE(u)->type == SERVICE_IDLE ? state_translation_table_idle : state_translation_table;
Michal Schmidt 99043c
+
Michal Schmidt 99043c
+        return table[SERVICE(u)->state];
Michal Schmidt 99043c
 }
Michal Schmidt 99043c
 
Michal Schmidt 99043c
 static const char *service_sub_state_to_string(Unit *u) {