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