core: enforce a ratelimiter when stopping units due to StopWhenUnneeded=1
authorLennart Poettering <lennart@poettering.net>
Tue, 19 May 2015 14:00:24 +0000 (16:00 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 19 May 2015 14:00:24 +0000 (16:00 +0200)
Otherwise we might end up in an endless stop loop.

http://lists.freedesktop.org/archives/systemd-devel/2015-April/030224.html

src/core/unit.c
src/core/unit.h

index f7d6289..956711d 100644 (file)
@@ -91,6 +91,8 @@ Unit *unit_new(Manager *m, size_t size) {
         u->unit_file_preset = -1;
         u->on_failure_job_mode = JOB_REPLACE;
 
+        RATELIMIT_INIT(u->check_unneeded_ratelimit, 10 * USEC_PER_SEC, 16);
+
         return u;
 }
 
@@ -1622,6 +1624,14 @@ static void unit_check_unneeded(Unit *u) {
                         if (unit_active_or_pending(other))
                                 return;
 
+        /* If stopping a unit fails continously we might enter a stop
+         * loop here, hence stop acting on the service being
+         * unnecessary after a while. */
+        if (!ratelimit_test(&u->check_unneeded_ratelimit)) {
+                log_unit_warning(u, "Unit not needed anymore, but not stopping since we tried this too often recently.");
+                return;
+        }
+
         log_unit_info(u, "Unit not needed anymore. Stopping.");
 
         /* Ok, nobody needs us anymore. Sniff. Then let's commit suicide */
index 62257c4..e0e76e5 100644 (file)
@@ -175,6 +175,9 @@ struct Unit {
         /* Error code when we didn't manage to load the unit (negative) */
         int load_error;
 
+        /* Make sure we never enter endless loops with the check unneeded logic */
+        RateLimit check_unneeded_ratelimit;
+
         /* Cached unit file state and preset */
         UnitFileState unit_file_state;
         int unit_file_preset;