assert(u->load_state == UNIT_STUB);
p->directory_mode = 0755;
+
+ p->trigger_limit.interval = 2 * USEC_PER_SEC;
+ p->trigger_limit.burst = 200;
}
void path_free_specs(Path *p) {
if (unit_stop_pending(UNIT(p)))
return;
+ if (!ratelimit_below(&p->trigger_limit)) {
+ log_unit_warning(UNIT(p), "Trigger limit hit, refusing further activation.");
+ path_enter_dead(p, PATH_FAILURE_TRIGGER_LIMIT_HIT);
+ return;
+ }
+
trigger = UNIT_TRIGGER(UNIT(p));
if (!trigger) {
log_unit_error(UNIT(p), "Unit to trigger vanished.");
[PATH_FAILURE_RESOURCES] = "resources",
[PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
[PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
+ [PATH_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
};
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
PATH_FAILURE_RESOURCES,
PATH_FAILURE_START_LIMIT_HIT,
PATH_FAILURE_UNIT_START_LIMIT_HIT,
+ PATH_FAILURE_TRIGGER_LIMIT_HIT,
_PATH_RESULT_MAX,
_PATH_RESULT_INVALID = -EINVAL,
} PathResult;
mode_t directory_mode;
PathResult result;
+
+ RateLimit trigger_limit;
};
void path_free_specs(Path *p);
# SPDX-License-Identifier: LGPL-2.1-or-later
[Unit]
-ConditionPathExists=!/tmp/nonexistent
+ConditionPathExists=/tmp/nonexistent
[Service]
ExecStart=true
[Service]
ExecStartPre=rm -f /failed /testok
Type=oneshot
+
+# Test that a path unit continuously triggering a service that fails condition checks eventually fails with
+# the trigger-limit-hit error.
ExecStart=rm -f /tmp/nonexistent
ExecStart=systemctl start test63.path
ExecStart=touch /tmp/test63
-# Make sure systemd has sufficient time to hit the start limit for test63.service.
+# Make sure systemd has sufficient time to hit the trigger limit for test63.path.
ExecStart=sleep 2
-ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = failed'
-ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = start-limit-hit'
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = inactive'
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = success'
ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = failed'
-ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = unit-start-limit-hit'
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = trigger-limit-hit'
+
+# Test that starting the service manually doesn't affect the path unit.
+ExecStart=rm -f /tmp/test63
+ExecStart=systemctl reset-failed
+ExecStart=systemctl start test63.path
+ExecStart=systemctl start test63.service
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P ActiveState)" = inactive'
+ExecStart=sh -x -c 'test "$(systemctl show test63.service -P Result)" = success'
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P ActiveState)" = active'
+ExecStart=sh -x -c 'test "$(systemctl show test63.path -P Result)" = success'
ExecStart=sh -x -c 'echo OK >/testok'