|
|
b7dd4d |
From 9d3f5e5d222308d29aad9bf7b2bfc440143a8606 Mon Sep 17 00:00:00 2001
|
|
|
62b62a |
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
|
|
62b62a |
Date: Fri, 17 Dec 2021 20:01:31 +0100
|
|
|
62b62a |
Subject: [PATCH] core: Add trigger limit for path units
|
|
|
62b62a |
|
|
|
62b62a |
When conditions fail on a service unit, a path unit can cause
|
|
|
62b62a |
PID 1 to busy loop as it keeps trying to activate the service unit.
|
|
|
62b62a |
To avoid this from happening, add a trigger limit to the path unit,
|
|
|
62b62a |
identical to the trigger limit we have for socket units.
|
|
|
62b62a |
|
|
|
62b62a |
Initially, let's start with a high limit and not make it configurable.
|
|
|
62b62a |
If needed, we can add properties to configure the rate limit similar
|
|
|
62b62a |
to the ones we have for socket units.
|
|
|
62b62a |
|
|
|
62b62a |
(cherry picked from commit aaae822b37aa3ca39aebb516fdc6bef36d730c25)
|
|
|
62b62a |
|
|
|
b7dd4d |
Resolves: #2114005
|
|
|
62b62a |
---
|
|
|
62b62a |
src/core/path.c | 10 ++++++++++
|
|
|
62b62a |
src/core/path.h | 3 +++
|
|
|
62b62a |
test/TEST-63-ISSUE-17433/test63.service | 2 +-
|
|
|
62b62a |
test/TEST-63-ISSUE-17433/testsuite.service | 21 +++++++++++++++++----
|
|
|
62b62a |
4 files changed, 31 insertions(+), 5 deletions(-)
|
|
|
62b62a |
|
|
|
62b62a |
diff --git a/src/core/path.c b/src/core/path.c
|
|
|
62b62a |
index c2facf0b16..b899bde0de 100644
|
|
|
62b62a |
--- a/src/core/path.c
|
|
|
62b62a |
+++ b/src/core/path.c
|
|
|
62b62a |
@@ -238,6 +238,9 @@ static void path_init(Unit *u) {
|
|
|
62b62a |
assert(u->load_state == UNIT_STUB);
|
|
|
62b62a |
|
|
|
62b62a |
p->directory_mode = 0755;
|
|
|
62b62a |
+
|
|
|
62b62a |
+ p->trigger_limit.interval = 2 * USEC_PER_SEC;
|
|
|
62b62a |
+ p->trigger_limit.burst = 200;
|
|
|
62b62a |
}
|
|
|
62b62a |
|
|
|
62b62a |
void path_free_specs(Path *p) {
|
|
|
62b62a |
@@ -467,6 +470,12 @@ static void path_enter_running(Path *p) {
|
|
|
62b62a |
if (unit_stop_pending(UNIT(p)))
|
|
|
62b62a |
return;
|
|
|
62b62a |
|
|
|
62b62a |
+ if (!ratelimit_below(&p->trigger_limit)) {
|
|
|
62b62a |
+ log_unit_warning(UNIT(p), "Trigger limit hit, refusing further activation.");
|
|
|
62b62a |
+ path_enter_dead(p, PATH_FAILURE_TRIGGER_LIMIT_HIT);
|
|
|
62b62a |
+ return;
|
|
|
62b62a |
+ }
|
|
|
62b62a |
+
|
|
|
62b62a |
trigger = UNIT_TRIGGER(UNIT(p));
|
|
|
62b62a |
if (!trigger) {
|
|
|
62b62a |
log_unit_error(UNIT(p), "Unit to trigger vanished.");
|
|
|
62b62a |
@@ -767,6 +776,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = {
|
|
|
62b62a |
[PATH_FAILURE_RESOURCES] = "resources",
|
|
|
62b62a |
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
|
|
|
62b62a |
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
|
|
|
62b62a |
+ [PATH_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
|
|
|
62b62a |
};
|
|
|
62b62a |
|
|
|
62b62a |
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
|
|
|
62b62a |
diff --git a/src/core/path.h b/src/core/path.h
|
|
|
62b62a |
index 8a69f06c13..12fd13fbe3 100644
|
|
|
62b62a |
--- a/src/core/path.h
|
|
|
62b62a |
+++ b/src/core/path.h
|
|
|
62b62a |
@@ -46,6 +46,7 @@ typedef enum PathResult {
|
|
|
62b62a |
PATH_FAILURE_RESOURCES,
|
|
|
62b62a |
PATH_FAILURE_START_LIMIT_HIT,
|
|
|
62b62a |
PATH_FAILURE_UNIT_START_LIMIT_HIT,
|
|
|
62b62a |
+ PATH_FAILURE_TRIGGER_LIMIT_HIT,
|
|
|
62b62a |
_PATH_RESULT_MAX,
|
|
|
62b62a |
_PATH_RESULT_INVALID = -1
|
|
|
62b62a |
} PathResult;
|
|
|
62b62a |
@@ -63,6 +64,8 @@ struct Path {
|
|
|
62b62a |
mode_t directory_mode;
|
|
|
62b62a |
|
|
|
62b62a |
PathResult result;
|
|
|
62b62a |
+
|
|
|
62b62a |
+ RateLimit trigger_limit;
|
|
|
62b62a |
};
|
|
|
62b62a |
|
|
|
62b62a |
void path_free_specs(Path *p);
|
|
|
62b62a |
diff --git a/test/TEST-63-ISSUE-17433/test63.service b/test/TEST-63-ISSUE-17433/test63.service
|
|
|
62b62a |
index c83801874d..6292434c5c 100644
|
|
|
62b62a |
--- a/test/TEST-63-ISSUE-17433/test63.service
|
|
|
62b62a |
+++ b/test/TEST-63-ISSUE-17433/test63.service
|
|
|
62b62a |
@@ -1,5 +1,5 @@
|
|
|
62b62a |
[Unit]
|
|
|
62b62a |
-ConditionPathExists=!/tmp/nonexistent
|
|
|
62b62a |
+ConditionPathExists=/tmp/nonexistent
|
|
|
62b62a |
|
|
|
62b62a |
[Service]
|
|
|
62b62a |
ExecStart=true
|
|
|
62b62a |
diff --git a/test/TEST-63-ISSUE-17433/testsuite.service b/test/TEST-63-ISSUE-17433/testsuite.service
|
|
|
62b62a |
index d3ca5b002b..39f9643890 100644
|
|
|
62b62a |
--- a/test/TEST-63-ISSUE-17433/testsuite.service
|
|
|
62b62a |
+++ b/test/TEST-63-ISSUE-17433/testsuite.service
|
|
|
62b62a |
@@ -4,14 +4,27 @@ Description=TEST-63-ISSUE-17433
|
|
|
62b62a |
[Service]
|
|
|
62b62a |
ExecStartPre=rm -f /failed /testok
|
|
|
62b62a |
Type=oneshot
|
|
|
62b62a |
+
|
|
|
62b62a |
+# Test that a path unit continuously triggering a service that fails condition checks eventually fails with
|
|
|
62b62a |
+# the trigger-limit-hit error.
|
|
|
62b62a |
ExecStart=rm -f /tmp/nonexistent
|
|
|
62b62a |
ExecStart=systemctl start test63.path
|
|
|
62b62a |
ExecStart=touch /tmp/test63
|
|
|
62b62a |
-# Make sure systemd has sufficient time to hit the start limit for test63.service.
|
|
|
62b62a |
+# Make sure systemd has sufficient time to hit the trigger limit for test63.path.
|
|
|
62b62a |
ExecStart=sleep 2
|
|
|
62b62a |
-ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = failed'
|
|
|
62b62a |
-ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = start-limit-hit'
|
|
|
62b62a |
+ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = inactive'
|
|
|
62b62a |
+ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = success'
|
|
|
62b62a |
# FIXME: The path remains active, which it should not
|
|
|
62b62a |
# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p ActiveState)" = failed'
|
|
|
62b62a |
-# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = unit-start-limit-hit'
|
|
|
62b62a |
+# ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = trigger-limit-hit'
|
|
|
62b62a |
+
|
|
|
62b62a |
+# Test that starting the service manually doesn't affect the path unit.
|
|
|
62b62a |
+ExecStart=rm -f /tmp/test63
|
|
|
62b62a |
+ExecStart=systemctl reset-failed
|
|
|
62b62a |
+ExecStart=systemctl start test63.path
|
|
|
62b62a |
+ExecStart=systemctl start test63.service
|
|
|
62b62a |
+ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p ActiveState)" = inactive'
|
|
|
62b62a |
+ExecStart=sh -x -c 'test "$(systemctl show test63.service --value -p Result)" = success'
|
|
|
62b62a |
+ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p ActiveState)" = active'
|
|
|
62b62a |
+ExecStart=sh -x -c 'test "$(systemctl show test63.path --value -p Result)" = success'
|
|
|
62b62a |
ExecStart=sh -x -c 'echo OK >/testok'
|