[systemd-devel] [RFC PATCH] service: add Restart option to execute StartLimitAction immediately

Michael Olbrich m.olbrich at pengutronix.de
Thu Mar 20 04:52:13 PDT 2014


---

Hi,

The idea is to reboot immediately when a service crashes or the watchdog
triggers. This is useful in embedded scenarios when there is only one
important service. There are use-cases where rebooting immediately instead
of trying to restart the application first makes sense.
The environment of the restarted application is not well defined. The
watchdog is for unexpected failures. So making sure that the application
behaves correctly can be difficult. When rebooting only takes a few
seconds, doing so may be more robust than trying to recover from an
undefined state.

This is an RFC for now. Mostly because I think the configuration is rather
awkward like this.
Hooking into Restart/StartLimitAction was the easiest way to handle this in
the code. But it doesn't feel natural to configure it like this. Any Ideas
on how to  express this in the unit file?

Regards,
Michael

 src/core/service.c | 23 ++++++++++++++++++-----
 src/core/service.h |  1 +
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/src/core/service.c b/src/core/service.c
index 78a2e06..ef494ba 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1832,6 +1832,8 @@ static int cgroup_good(Service *s) {
         return !r;
 }
 
+static int service_start_limit_execute(Service *s);
+
 static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) {
         int r;
         assert(s);
@@ -1843,6 +1845,10 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart)
 
         if (allow_restart &&
             !s->forbid_restart &&
+            s->restart == SERVICE_RESTART_FAIL) {
+                service_start_limit_execute(s);
+        } else if (allow_restart &&
+            !s->forbid_restart &&
             (s->restart == SERVICE_RESTART_ALWAYS ||
              (s->restart == SERVICE_RESTART_ON_SUCCESS && s->result == SERVICE_SUCCESS) ||
              (s->restart == SERVICE_RESTART_ON_FAILURE && s->result != SERVICE_SUCCESS) ||
@@ -2363,12 +2369,9 @@ fail:
         service_enter_stop(s, SERVICE_FAILURE_RESOURCES);
 }
 
-static int service_start_limit_test(Service *s) {
+static int service_start_limit_execute(Service *s) {
         assert(s);
 
-        if (ratelimit_test(&s->start_limit))
-                return 0;
-
         switch (s->start_limit_action) {
 
         case SERVICE_START_LIMIT_NONE:
@@ -2416,6 +2419,15 @@ static int service_start_limit_test(Service *s) {
         return -ECANCELED;
 }
 
+static int service_start_limit_test(Service *s) {
+        assert(s);
+
+        if (ratelimit_test(&s->start_limit))
+                return 0;
+
+        return service_start_limit_execute(s);
+}
+
 static int service_start(Unit *u) {
         Service *s = SERVICE(u);
         int r;
@@ -3754,7 +3766,8 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = {
         [SERVICE_RESTART_ON_FAILURE] = "on-failure",
         [SERVICE_RESTART_ON_WATCHDOG] = "on-watchdog",
         [SERVICE_RESTART_ON_ABORT] = "on-abort",
-        [SERVICE_RESTART_ALWAYS] = "always"
+        [SERVICE_RESTART_ALWAYS] = "always",
+        [SERVICE_RESTART_FAIL] = "fail"
 };
 
 DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart);
diff --git a/src/core/service.h b/src/core/service.h
index 1992926..2cdc7ad 100644
--- a/src/core/service.h
+++ b/src/core/service.h
@@ -56,6 +56,7 @@ typedef enum ServiceRestart {
         SERVICE_RESTART_ON_WATCHDOG,
         SERVICE_RESTART_ON_ABORT,
         SERVICE_RESTART_ALWAYS,
+        SERVICE_RESTART_FAIL,
         _SERVICE_RESTART_MAX,
         _SERVICE_RESTART_INVALID = -1
 } ServiceRestart;
-- 
1.9.1



More information about the systemd-devel mailing list