b7dd4d
From afb5e76925f7f4992252cc392dac4dda6c4faf69 Mon Sep 17 00:00:00 2001
ff479f
From: Lennart Poettering <lennart@poettering.net>
ff479f
Date: Fri, 11 Sep 2020 19:57:09 +0200
ff479f
Subject: [PATCH] core: propagate unit start limit hit state to triggering path
ff479f
 unit
ff479f
ff479f
We already do this for socket and automount units, do it for path units
ff479f
too: if the triggered service keeps hitting the start limit, then fail
ff479f
the triggering unit too, so that we don#t busy loop forever.
ff479f
ff479f
(Note that this leaves only timer units out in the cold for this kind of
ff479f
protection, but it shouldn't matter there, as they are naturally
ff479f
protected against busy loops: they are scheduled by time anyway).
ff479f
ff479f
Fixes: #16669
ff479f
(cherry picked from commit 47ab8f73e3468b6e5a48218eacdb830e978d2cfd)
ff479f
b7dd4d
Related: #2065322
ff479f
---
ff479f
 src/core/path.c | 15 +++++++++++++++
ff479f
 src/core/path.h |  1 +
ff479f
 2 files changed, 16 insertions(+)
ff479f
ff479f
diff --git a/src/core/path.c b/src/core/path.c
ff479f
index a7c2e0b7c1..c2facf0b16 100644
ff479f
--- a/src/core/path.c
ff479f
+++ b/src/core/path.c
ff479f
@@ -701,6 +701,20 @@ static void path_trigger_notify(Unit *u, Unit *other) {
ff479f
         /* Filter out invocations with bogus state */
ff479f
         assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
ff479f
 
ff479f
+        /* Don't propagate state changes from the triggered unit if we are already down */
ff479f
+        if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING))
ff479f
+                return;
ff479f
+
ff479f
+        /* Propagate start limit hit state */
ff479f
+        if (other->start_limit_hit) {
ff479f
+                path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT);
ff479f
+                return;
ff479f
+        }
ff479f
+
ff479f
+        /* Don't propagate anything if there's still a job queued */
ff479f
+        if (other->job)
ff479f
+                return;
ff479f
+
ff479f
         if (p->state == PATH_RUNNING &&
ff479f
             UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
ff479f
                 log_unit_debug(UNIT(p), "Got notified about unit deactivation.");
ff479f
@@ -752,6 +766,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
ff479f
         [PATH_SUCCESS] = "success",
ff479f
         [PATH_FAILURE_RESOURCES] = "resources",
ff479f
         [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
ff479f
+        [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
ff479f
 };
ff479f
 
ff479f
 DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
ff479f
diff --git a/src/core/path.h b/src/core/path.h
ff479f
index 4d4b6236c2..8a69f06c13 100644
ff479f
--- a/src/core/path.h
ff479f
+++ b/src/core/path.h
ff479f
@@ -45,6 +45,7 @@ typedef enum PathResult {
ff479f
         PATH_SUCCESS,
ff479f
         PATH_FAILURE_RESOURCES,
ff479f
         PATH_FAILURE_START_LIMIT_HIT,
ff479f
+        PATH_FAILURE_UNIT_START_LIMIT_HIT,
ff479f
         _PATH_RESULT_MAX,
ff479f
         _PATH_RESULT_INVALID = -1
ff479f
 } PathResult;