summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-05-19 16:00:24 +0200
committerLennart Poettering <lennart@poettering.net>2015-05-19 16:00:24 +0200
commitbea355dac94e82697aa98e25d80ee4248263bf92 (patch)
tree21275e16a068ef3ce4e2d6518eb9de57021c4672 /src
parentf3b85044c845de03de05135c1dd5f3298bf3e5a2 (diff)
core: enforce a ratelimiter when stopping units due to StopWhenUnneeded=1
Otherwise we might end up in an endless stop loop. http://lists.freedesktop.org/archives/systemd-devel/2015-April/030224.html
Diffstat (limited to 'src')
-rw-r--r--src/core/unit.c10
-rw-r--r--src/core/unit.h3
2 files changed, 13 insertions, 0 deletions
diff --git a/src/core/unit.c b/src/core/unit.c
index f7d6289905..956711d500 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -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 */
diff --git a/src/core/unit.h b/src/core/unit.h
index 62257c403e..e0e76e520c 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -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;