import systemd-239-60.el8

This commit is contained in:
CentOS Sources 2022-07-02 00:14:39 +00:00 committed by Stepan Oksanichenko
parent 07ee01dc0d
commit 3d4c7390b9
11 changed files with 891 additions and 1 deletions

View File

@ -0,0 +1,62 @@
From a46d3732a4f8baacf1be3e5e0ac152119fe26d4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Renaud=20M=C3=A9trich?= <rmetrich@redhat.com>
Date: Fri, 2 Oct 2020 17:30:35 +0200
Subject: [PATCH] unit: don't emit PropertiesChanged signal if adding a
dependency to a unit is a no-op
(cherry picked from commit 5177cb0a9add4ae568cff6e6f7c2b3c77760c343)
Resolves: #1948480
---
src/core/unit.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 68affa2c0e..e3e534ea2e 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -2818,6 +2818,9 @@ int unit_add_dependency(
};
Unit *original_u = u, *original_other = other;
int r;
+ /* Helper to know whether sending a notification is necessary or not:
+ * if the dependency is already there, no need to notify! */
+ bool noop = true;
assert(u);
assert(d >= 0 && d < _UNIT_DEPENDENCY_MAX);
@@ -2842,24 +2845,33 @@ int unit_add_dependency(
r = unit_add_dependency_hashmap(u->dependencies + d, other, mask, 0);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
if (inverse_table[d] != _UNIT_DEPENDENCY_INVALID && inverse_table[d] != d) {
r = unit_add_dependency_hashmap(other->dependencies + inverse_table[d], u, 0, mask);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
}
if (add_reference) {
r = unit_add_dependency_hashmap(u->dependencies + UNIT_REFERENCES, other, mask, 0);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
r = unit_add_dependency_hashmap(other->dependencies + UNIT_REFERENCED_BY, u, 0, mask);
if (r < 0)
return r;
+ else if (r > 0)
+ noop = false;
}
- unit_add_to_dbus_queue(u);
+ if (!noop)
+ unit_add_to_dbus_queue(u);
return 0;
}

View File

@ -0,0 +1,34 @@
From f784cdd269ccba28e3e14b24ecd33ab9db148403 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 7 Apr 2021 23:24:25 +0200
Subject: [PATCH] tests: make inverted tests actually count
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
"! test ..." does not cause the script to fail, even with set -e.
IIUC, bash treats this command as part of an expression line, as it
would if 'test ... && ...' was used. Failing expression lines do not
terminate the script.
This fixes the obvious cases by changing '! test' → 'test !'.
Then the inversion happens internally in test and bash will propagate
the failure.
(cherry picked from commit ffa328f060f437f3e1f0f0cb13513ee3dd9c3da5)
Related: #2087152
---
test/TEST-22-TMPFILES/test-01.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/TEST-22-TMPFILES/test-01.sh b/test/TEST-22-TMPFILES/test-01.sh
index d233e37fb2..b10b5aaa1a 100755
--- a/test/TEST-22-TMPFILES/test-01.sh
+++ b/test/TEST-22-TMPFILES/test-01.sh
@@ -10,4 +10,4 @@ rm -fr /tmp/test
echo "e /tmp/test - root root 1d" | systemd-tmpfiles --create -
-! test -e /tmp/test
+test ! -e /tmp/test

View File

@ -0,0 +1,123 @@
From d153f9ff573b191076b843118e825f71227dbc01 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Thu, 8 Apr 2021 01:27:33 +0200
Subject: [PATCH] TEST-*: make failure tests actually fail on failure
Here the intent was actually correct, and the tests still pass when the check
is made effective.
(cherry picked from commit 4e20fe27950e14e8a082a74515f347546a9371d0)
Related: #2087152
---
test/TEST-03-JOBS/test-jobs.sh | 8 ++++----
test/TEST-04-JOURNAL/test-journal.sh | 4 ++--
test/TEST-18-FAILUREACTION/testsuite.sh | 2 +-
test/TEST-20-MAINPIDGAMES/testsuite.sh | 14 ++++++++++++--
test/TEST-23-TYPE-EXEC/testsuite.sh | 4 ++--
5 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/test/TEST-03-JOBS/test-jobs.sh b/test/TEST-03-JOBS/test-jobs.sh
index 42190cf478..4ff53e0ade 100755
--- a/test/TEST-03-JOBS/test-jobs.sh
+++ b/test/TEST-03-JOBS/test-jobs.sh
@@ -18,7 +18,7 @@ systemctl start --job-mode=ignore-dependencies hello
END_SEC=$(date -u '+%s')
ELAPSED=$(($END_SEC-$START_SEC))
-[ "$ELAPSED" -lt 3 ]
+test "$ELAPSED" -lt 3
# sleep should still be running, hello not.
systemctl list-jobs > /root/list-jobs.txt
@@ -27,11 +27,11 @@ grep 'hello\.service' /root/list-jobs.txt && exit 1
systemctl stop sleep.service hello-after-sleep.target
# Some basic testing that --show-transaction does something useful
-! systemctl is-active systemd-importd
+systemctl is-active systemd-importd && { echo 'unexpected success'; exit 1; }
systemctl -T start systemd-importd
systemctl is-active systemd-importd
systemctl --show-transaction stop systemd-importd
-! systemctl is-active systemd-importd
+systemctl is-active systemd-importd && { echo 'unexpected success'; exit 1; }
# Test for a crash when enqueuing a JOB_NOP when other job already exists
systemctl start --no-block hello-after-sleep.target
@@ -79,7 +79,7 @@ ELAPSED=$(($END_SEC-$START_SEC))
# wait5fail fails, so systemctl should fail
START_SEC=$(date -u '+%s')
-! systemctl start --wait wait2.service wait5fail.service || exit 1
+systemctl start --wait wait2.service wait5fail.service && { echo 'unexpected success'; exit 1; }
END_SEC=$(date -u '+%s')
ELAPSED=$(($END_SEC-$START_SEC))
[[ "$ELAPSED" -ge 5 ]] && [[ "$ELAPSED" -le 7 ]] || exit 1
diff --git a/test/TEST-04-JOURNAL/test-journal.sh b/test/TEST-04-JOURNAL/test-journal.sh
index 52a6ee84d1..a3db1a7472 100755
--- a/test/TEST-04-JOURNAL/test-journal.sh
+++ b/test/TEST-04-JOURNAL/test-journal.sh
@@ -60,8 +60,8 @@ journalctl -b -o export --output-fields=MESSAGE,FOO --output-fields=PRIORITY,MES
grep -q '^__CURSOR=' /output
grep -q '^MESSAGE=foo$' /output
grep -q '^PRIORITY=6$' /output
-! grep -q '^FOO=' /output
-! grep -q '^SYSLOG_FACILITY=' /output
+grep '^FOO=' /output && { echo 'unexpected success'; exit 1; }
+grep '^SYSLOG_FACILITY=' /output && { echo 'unexpected success'; exit 1; }
# https://github.com/systemd/systemd/issues/13708
ID=$(journalctl --new-id128 | sed -n 2p)
diff --git a/test/TEST-18-FAILUREACTION/testsuite.sh b/test/TEST-18-FAILUREACTION/testsuite.sh
index 1867cc3c47..21b055d6ef 100755
--- a/test/TEST-18-FAILUREACTION/testsuite.sh
+++ b/test/TEST-18-FAILUREACTION/testsuite.sh
@@ -5,7 +5,7 @@ set -ex
set -o pipefail
systemd-run --wait -p FailureAction=poweroff true
-! systemd-run --wait -p SuccessAction=poweroff false
+systemd-run --wait -p SuccessAction=poweroff false && { echo 'unexpected success'; exit 1; }
if test -f /firstphase ; then
echo OK > /firstphase
diff --git a/test/TEST-20-MAINPIDGAMES/testsuite.sh b/test/TEST-20-MAINPIDGAMES/testsuite.sh
index 0e1a116b07..d1bfdd7a2d 100755
--- a/test/TEST-20-MAINPIDGAMES/testsuite.sh
+++ b/test/TEST-20-MAINPIDGAMES/testsuite.sh
@@ -128,8 +128,18 @@ test -f /run/mainpidsh3/pid
EOF
chmod 755 /dev/shm/mainpid3.sh
-# This has to fail, as we shouldn't accept the dangerous PID file, and then inotify-wait on it to be corrected which we never do
-! systemd-run --unit=mainpidsh3.service -p StandardOutput=tty -p StandardError=tty -p Type=forking -p RuntimeDirectory=mainpidsh3 -p PIDFile=/run/mainpidsh3/pid -p DynamicUser=1 -p TimeoutStartSec=2s /dev/shm/mainpid3.sh
+# This has to fail, as we shouldn't accept the dangerous PID file, and then
+# inotify-wait on it to be corrected which we never do.
+systemd-run --unit=mainpidsh3.service \
+ -p StandardOutput=tty \
+ -p StandardError=tty \
+ -p Type=forking \
+ -p RuntimeDirectory=mainpidsh3 \
+ -p PIDFile=/run/mainpidsh3/pid \
+ -p DynamicUser=1 \
+ -p TimeoutStartSec=2s \
+ /dev/shm/mainpid3.sh \
+ && { echo 'unexpected success'; exit 1; }
# Test that this failed due to timeout, and not some other error
test `systemctl show -p Result --value mainpidsh3.service` = timeout
diff --git a/test/TEST-23-TYPE-EXEC/testsuite.sh b/test/TEST-23-TYPE-EXEC/testsuite.sh
index e0c34cfd04..beb7fd2e38 100755
--- a/test/TEST-23-TYPE-EXEC/testsuite.sh
+++ b/test/TEST-23-TYPE-EXEC/testsuite.sh
@@ -18,8 +18,8 @@ systemd-run --unit=three -p Type=simple /tmp/brokenbinary
# And now, do the same with Type=exec, where the latter two should fail
systemd-run --unit=four -p Type=exec /bin/sleep infinity
-! systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity
-! systemd-run --unit=six -p Type=exec /tmp/brokenbinary
+systemd-run --unit=five -p Type=exec -p User=idontexist /bin/sleep infinity && { echo 'unexpected success'; exit 1; }
+systemd-run --unit=six -p Type=exec /tmp/brokenbinary && { echo 'unexpected success'; exit 1; }
# For issue #20933

View File

@ -0,0 +1,69 @@
From cd8518b7f4ebfda9955bf0b649cf759c45e729f1 Mon Sep 17 00:00:00 2001
From: Jan Macku <jamacku@redhat.com>
Date: Mon, 6 Jun 2022 15:40:20 +0200
Subject: [PATCH] ci(Mergify): configuration update
Add rules for needs-ci label management
RHEL-only
Related: #2087152
---
.mergify.yml | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 .mergify.yml
diff --git a/.mergify.yml b/.mergify.yml
new file mode 100644
index 0000000000..6fa400effd
--- /dev/null
+++ b/.mergify.yml
@@ -0,0 +1,48 @@
+# doc: https://docs.mergify.com
+---
+
+pull_request_rules:
+ - name: Add `needs-ci` label on CI fail
+ conditions:
+ - or:
+ # Unit tests
+ - -check-success=build (stream8, GCC)
+ - -check-success=build (stream8, GCC_ASAN)
+ # CentOS Stream CI
+ - -check-success=CentOS CI (CentOS Stream 8)
+ # LGTM
+ - and:
+ - "-check-success=LGTM analysis: JavaScript"
+ - "-check-neutral=LGTM analysis: JavaScript"
+ - and:
+ - "-check-success=LGTM analysis: Python"
+ - "-check-neutral=LGTM analysis: Python"
+ - and:
+ - "-check-success=LGTM analysis: C/C++"
+ - "-check-neutral=LGTM analysis: C/C++"
+ actions:
+ label:
+ add:
+ - needs-ci
+
+ - name: Remove `needs-ci` label on CI success
+ conditions:
+ # Unit tests
+ - check-success=build (stream8, GCC)
+ - check-success=build (stream8, GCC_ASAN)
+ # CentOS Stream CI
+ - check-success=CentOS CI (CentOS Stream 8)
+ # LGTM
+ - or:
+ - "check-success=LGTM analysis: JavaScript"
+ - "check-neutral=LGTM analysis: JavaScript"
+ - or:
+ - "check-success=LGTM analysis: Python"
+ - "check-neutral=LGTM analysis: Python"
+ - or:
+ - "check-success=LGTM analysis: C/C++"
+ - "check-neutral=LGTM analysis: C/C++"
+ actions:
+ label:
+ remove:
+ - needs-ci

View File

@ -0,0 +1,122 @@
From e5121fbb839a36055e5fdab1b9d92dc42f495f29 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 11 Sep 2020 19:49:33 +0200
Subject: [PATCH] core: propagate triggered unit in more load states
In 4c2ef3276735ad9f7fccf33f5bdcbe7d8751e7ec we enabled propagating
triggered unit state to the triggering unit for service units in more
load states, so that we don't accidentally stop tracking state
correctly.
Do the same for our other triggering unit states: automounts, paths, and
timers.
Also, make this an assertion rather than a simple test. After all it
should never happen that we get called for half-loaded units or units of
the wrong type. The load routines should already have made this
impossible.
(cherry picked from commit 0377cd2936ae5cac0c9d76a4b58889f121c097c4)
Related: #2065322
---
src/core/automount.c | 4 ++--
src/core/path.c | 7 +++----
src/core/socket.c | 4 ++--
src/core/timer.c | 4 ++--
src/core/transaction.c | 2 +-
src/core/unit.h | 4 ++++
6 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/src/core/automount.c b/src/core/automount.c
index f212620c8f..c1c513d4a5 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -492,8 +492,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) {
assert(other);
/* Filter out invocations with bogus state */
- if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT)
- return;
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
+ assert(other->type == UNIT_MOUNT);
/* Don't propagate state changes from the mount if we are already down */
if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING))
diff --git a/src/core/path.c b/src/core/path.c
index 58f490589d..a7c2e0b7c1 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -696,11 +696,10 @@ static void path_trigger_notify(Unit *u, Unit *other) {
assert(u);
assert(other);
- /* Invoked whenever the unit we trigger changes state or gains
- * or loses a job */
+ /* Invoked whenever the unit we trigger changes state or gains or loses a job */
- if (other->load_state != UNIT_LOADED)
- return;
+ /* Filter out invocations with bogus state */
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
if (p->state == PATH_RUNNING &&
UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
diff --git a/src/core/socket.c b/src/core/socket.c
index 3589300e68..74c1cc70cb 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -3190,8 +3190,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
assert(other);
/* Filter out invocations with bogus state */
- if (other->load_state != UNIT_LOADED || other->type != UNIT_SERVICE)
- return;
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
+ assert(other->type == UNIT_SERVICE);
/* Don't propagate state changes from the service if we are already down */
if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING))
diff --git a/src/core/timer.c b/src/core/timer.c
index 684180bf99..990f05fee4 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -745,8 +745,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) {
assert(u);
assert(other);
- if (other->load_state != UNIT_LOADED)
- return;
+ /* Filter out invocations with bogus state */
+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state));
/* Reenable all timers that depend on unit state */
LIST_FOREACH(value, v, t->values)
diff --git a/src/core/transaction.c b/src/core/transaction.c
index ee5b39fef4..8196aba927 100644
--- a/src/core/transaction.c
+++ b/src/core/transaction.c
@@ -915,7 +915,7 @@ int transaction_add_job_and_dependencies(
/* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set
* temporarily. */
- if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED))
+ if (!UNIT_IS_LOAD_COMPLETE(unit->load_state))
return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id);
if (type != JOB_STOP) {
diff --git a/src/core/unit.h b/src/core/unit.h
index 0cd259411f..b8b914711f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -47,6 +47,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) {
return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED);
}
+static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) {
+ return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED;
+}
+
/* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We
* use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be
* created as a result of multiple "reasons", hence the bitmask. */

View File

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

View File

@ -0,0 +1,31 @@
From 3392b2fb9e4920e9238a09c774252dc0d0183903 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Sat, 30 Oct 2021 22:12:06 +0100
Subject: [PATCH] core: Move 'r' variable declaration to start of unit_start()
(cherry picked from commit 5f37c1a955e399756c4137d22f7f0f45a619f425)
Related: #2065322
---
src/core/unit.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index e3e534ea2e..4fd9af87b7 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1725,12 +1725,13 @@ static bool unit_verify_deps(Unit *u) {
int unit_start(Unit *u) {
UnitActiveState state;
Unit *following;
+ int r;
assert(u);
/* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */
if (UNIT_VTABLE(u)->can_start) {
- int r = UNIT_VTABLE(u)->can_start(u);
+ r = UNIT_VTABLE(u)->can_start(u);
if (r < 0)
return r;
}

View File

@ -0,0 +1,49 @@
From 8c81776212d0aa44f5ae20635079bd6ce76d16ac Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Tue, 19 Oct 2021 10:45:48 +0100
Subject: [PATCH] core: Delay start rate limit check when starting a unit
Doing start rate limit checks before doing condition checks made
condition check failures count towards the start rate limit which
broke existing assumptions (see #21025). Run the rate limit checks
after the condition checks again to restore the previous behaviour.
(cherry picked from commit ce2146f5256659c7fb53a7d5b9dc551252e27e7e)
Related: #2065322
---
src/core/unit.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/core/unit.c b/src/core/unit.c
index 4fd9af87b7..b825e2418c 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1729,13 +1729,6 @@ int unit_start(Unit *u) {
assert(u);
- /* Check our ability to start early so that failure conditions don't cause us to enter a busy loop. */
- if (UNIT_VTABLE(u)->can_start) {
- r = UNIT_VTABLE(u)->can_start(u);
- if (r < 0)
- return r;
- }
-
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
* is not startable by the user. This is relied on to detect when we need to wait for units and when
* waiting is finished. */
@@ -1790,6 +1783,13 @@ int unit_start(Unit *u) {
return unit_start(following);
}
+ /* Check start rate limiting early so that failure conditions don't cause us to enter a busy loop. */
+ if (UNIT_VTABLE(u)->can_start) {
+ r = UNIT_VTABLE(u)->can_start(u);
+ if (r < 0)
+ return r;
+ }
+
/* If it is stopped, but we cannot start it, then fail */
if (!UNIT_VTABLE(u)->start)
return -EBADR;

View File

@ -0,0 +1,258 @@
From 2820f1706275acd787c72d9a57892200566f0bbe Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Mon, 18 Oct 2021 14:17:02 +0200
Subject: [PATCH] core: Propagate condition failed state to triggering units.
Alternative to https://github.com/systemd/systemd/pull/20531.
Whenever a service triggered by another unit fails condition checks,
stop the triggering unit to prevent systemd busy looping trying to
start the triggered unit.
(cherry picked from commit 12ab94a1e4961a39c32efb60b71866ab588d3ea2)
Resolves: #2065322
---
src/core/automount.c | 14 ++++++++++----
src/core/automount.h | 1 +
src/core/path.c | 16 +++++++++++-----
src/core/path.h | 1 +
src/core/socket.c | 28 +++++++++++++++++++---------
src/core/socket.h | 1 +
src/core/timer.c | 12 +++++++++---
src/core/timer.h | 1 +
src/core/unit.c | 10 ++++++++++
src/core/unit.h | 2 ++
10 files changed, 65 insertions(+), 21 deletions(-)
diff --git a/src/core/automount.c b/src/core/automount.c
index c1c513d4a5..bac3b2fab7 100644
--- a/src/core/automount.c
+++ b/src/core/automount.c
@@ -776,6 +776,11 @@ static void automount_enter_running(Automount *a) {
goto fail;
}
+ if (unit_has_failed_condition_or_assert(trigger)) {
+ automount_enter_dead(a, AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED);
+ return;
+ }
+
r = manager_add_job(UNIT(a)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
if (r < 0) {
log_unit_warning(UNIT(a), "Failed to queue mount startup job: %s", bus_error_message(&error, r));
@@ -1087,10 +1092,11 @@ static int automount_can_start(Unit *u) {
}
static const char* const automount_result_table[_AUTOMOUNT_RESULT_MAX] = {
- [AUTOMOUNT_SUCCESS] = "success",
- [AUTOMOUNT_FAILURE_RESOURCES] = "resources",
- [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
- [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
+ [AUTOMOUNT_SUCCESS] = "success",
+ [AUTOMOUNT_FAILURE_RESOURCES] = "resources",
+ [AUTOMOUNT_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT] = "mount-start-limit-hit",
+ [AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED] = "mount-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(automount_result, AutomountResult);
diff --git a/src/core/automount.h b/src/core/automount.h
index 21dd1c0774..a7417d195c 100644
--- a/src/core/automount.h
+++ b/src/core/automount.h
@@ -10,6 +10,7 @@ typedef enum AutomountResult {
AUTOMOUNT_FAILURE_RESOURCES,
AUTOMOUNT_FAILURE_START_LIMIT_HIT,
AUTOMOUNT_FAILURE_MOUNT_START_LIMIT_HIT,
+ AUTOMOUNT_FAILURE_MOUNT_CONDITION_FAILED,
_AUTOMOUNT_RESULT_MAX,
_AUTOMOUNT_RESULT_INVALID = -1
} AutomountResult;
diff --git a/src/core/path.c b/src/core/path.c
index c2facf0b16..bf7e1bf3c2 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -453,7 +453,7 @@ static void path_enter_dead(Path *p, PathResult f) {
else
unit_log_failure(UNIT(p), path_result_to_string(p->result));
- path_set_state(p, p->result != PATH_SUCCESS ? PATH_FAILED : PATH_DEAD);
+ path_set_state(p, p->result == PATH_SUCCESS ? PATH_DEAD : PATH_FAILED);
}
static void path_enter_running(Path *p) {
@@ -711,6 +711,11 @@ static void path_trigger_notify(Unit *u, Unit *other) {
return;
}
+ if (unit_has_failed_condition_or_assert(other)) {
+ path_enter_dead(p, PATH_FAILURE_UNIT_CONDITION_FAILED);
+ return;
+ }
+
/* Don't propagate anything if there's still a job queued */
if (other->job)
return;
@@ -763,10 +768,11 @@ static const char* const path_type_table[_PATH_TYPE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(path_type, PathType);
static const char* const path_result_table[_PATH_RESULT_MAX] = {
- [PATH_SUCCESS] = "success",
- [PATH_FAILURE_RESOURCES] = "resources",
- [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
- [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
+ [PATH_SUCCESS] = "success",
+ [PATH_FAILURE_RESOURCES] = "resources",
+ [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit",
+ [PATH_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult);
diff --git a/src/core/path.h b/src/core/path.h
index 8a69f06c13..0ad6bd12c6 100644
--- a/src/core/path.h
+++ b/src/core/path.h
@@ -46,6 +46,7 @@ typedef enum PathResult {
PATH_FAILURE_RESOURCES,
PATH_FAILURE_START_LIMIT_HIT,
PATH_FAILURE_UNIT_START_LIMIT_HIT,
+ PATH_FAILURE_UNIT_CONDITION_FAILED,
_PATH_RESULT_MAX,
_PATH_RESULT_INVALID = -1
} PathResult;
diff --git a/src/core/socket.c b/src/core/socket.c
index 74c1cc70cb..6f9a0f7575 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2272,6 +2272,15 @@ static void socket_enter_running(Socket *s, int cfd) {
goto refuse;
}
+ if (UNIT_ISSET(s->service) && cfd < 0) {
+ Unit *service = UNIT_DEREF(s->service);
+
+ if (unit_has_failed_condition_or_assert(service)) {
+ socket_enter_dead(s, SOCKET_FAILURE_SERVICE_CONDITION_FAILED);
+ return;
+ }
+ }
+
if (cfd < 0) {
bool pending = false;
Unit *other;
@@ -3287,15 +3296,16 @@ static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
- [SOCKET_SUCCESS] = "success",
- [SOCKET_FAILURE_RESOURCES] = "resources",
- [SOCKET_FAILURE_TIMEOUT] = "timeout",
- [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
- [SOCKET_FAILURE_SIGNAL] = "signal",
- [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
- [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
- [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
- [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit"
+ [SOCKET_SUCCESS] = "success",
+ [SOCKET_FAILURE_RESOURCES] = "resources",
+ [SOCKET_FAILURE_TIMEOUT] = "timeout",
+ [SOCKET_FAILURE_EXIT_CODE] = "exit-code",
+ [SOCKET_FAILURE_SIGNAL] = "signal",
+ [SOCKET_FAILURE_CORE_DUMP] = "core-dump",
+ [SOCKET_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [SOCKET_FAILURE_TRIGGER_LIMIT_HIT] = "trigger-limit-hit",
+ [SOCKET_FAILURE_SERVICE_START_LIMIT_HIT] = "service-start-limit-hit",
+ [SOCKET_FAILURE_SERVICE_CONDITION_FAILED] = "service-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
diff --git a/src/core/socket.h b/src/core/socket.h
index 2409dbf2a0..b171b94316 100644
--- a/src/core/socket.h
+++ b/src/core/socket.h
@@ -39,6 +39,7 @@ typedef enum SocketResult {
SOCKET_FAILURE_START_LIMIT_HIT,
SOCKET_FAILURE_TRIGGER_LIMIT_HIT,
SOCKET_FAILURE_SERVICE_START_LIMIT_HIT,
+ SOCKET_FAILURE_SERVICE_CONDITION_FAILED,
_SOCKET_RESULT_MAX,
_SOCKET_RESULT_INVALID = -1
} SocketResult;
diff --git a/src/core/timer.c b/src/core/timer.c
index 990f05fee4..3c8d89771d 100644
--- a/src/core/timer.c
+++ b/src/core/timer.c
@@ -567,6 +567,11 @@ static void timer_enter_running(Timer *t) {
return;
}
+ if (unit_has_failed_condition_or_assert(trigger)) {
+ timer_enter_dead(t, TIMER_FAILURE_UNIT_CONDITION_FAILED);
+ return;
+ }
+
r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, NULL, &error, NULL);
if (r < 0)
goto fail;
@@ -850,9 +855,10 @@ static const char* const timer_base_table[_TIMER_BASE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
- [TIMER_SUCCESS] = "success",
- [TIMER_FAILURE_RESOURCES] = "resources",
- [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [TIMER_SUCCESS] = "success",
+ [TIMER_FAILURE_RESOURCES] = "resources",
+ [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
+ [TIMER_FAILURE_UNIT_CONDITION_FAILED] = "unit-condition-failed",
};
DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
diff --git a/src/core/timer.h b/src/core/timer.h
index 833aadb0b8..d23e19d622 100644
--- a/src/core/timer.h
+++ b/src/core/timer.h
@@ -32,6 +32,7 @@ typedef enum TimerResult {
TIMER_SUCCESS,
TIMER_FAILURE_RESOURCES,
TIMER_FAILURE_START_LIMIT_HIT,
+ TIMER_FAILURE_UNIT_CONDITION_FAILED,
_TIMER_RESULT_MAX,
_TIMER_RESULT_INVALID = -1
} TimerResult;
diff --git a/src/core/unit.c b/src/core/unit.c
index b825e2418c..c00d30e837 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -5657,6 +5657,16 @@ int unit_thaw_vtable_common(Unit *u) {
return unit_cgroup_freezer_action(u, FREEZER_THAW);
}
+bool unit_has_failed_condition_or_assert(Unit *u) {
+ if (dual_timestamp_is_set(&u->condition_timestamp) && !u->condition_result)
+ return true;
+
+ if (dual_timestamp_is_set(&u->assert_timestamp) && !u->assert_result)
+ return true;
+
+ return false;
+}
+
static const char* const collect_mode_table[_COLLECT_MODE_MAX] = {
[COLLECT_INACTIVE] = "inactive",
[COLLECT_INACTIVE_OR_FAILED] = "inactive-or-failed",
diff --git a/src/core/unit.h b/src/core/unit.h
index b8b914711f..a924bd2e83 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -847,6 +847,8 @@ void unit_thawed(Unit *u);
int unit_freeze_vtable_common(Unit *u);
int unit_thaw_vtable_common(Unit *u);
+bool unit_has_failed_condition_or_assert(Unit *u);
+
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full(unit, level, error, ...) \

View File

@ -0,0 +1,52 @@
From 4dbe6568d5bcc082b13f3ef4d323d1669f16095c Mon Sep 17 00:00:00 2001
From: Michal Sekletar <msekleta@redhat.com>
Date: Mon, 30 May 2022 11:55:41 +0200
Subject: [PATCH] unit: check for mount rate limiting before checking active
state
Having this check as part of mount_can_start() is too late because
UNIT(u)->can_start() virtual method is called after checking the active
state of unit in unit_start().
We need to hold off running mount start jobs when /p/s/mountinfo monitor
is rate limited even when given mount unit is already active.
Fixes #20329
(cherry picked from commit b161bc394b2cc8b271dda9208e310cc2af0cc29d)
Resolves: #2095744
---
src/core/mount.c | 3 ---
src/core/unit.c | 4 ++++
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/core/mount.c b/src/core/mount.c
index 9547cb9b29..d37b5731f8 100644
--- a/src/core/mount.c
+++ b/src/core/mount.c
@@ -1999,9 +1999,6 @@ static int mount_can_start(Unit *u) {
assert(m);
- if (sd_event_source_is_ratelimited(u->manager->mount_event_source))
- return -EAGAIN;
-
r = unit_test_start_limit(u);
if (r < 0) {
mount_enter_dead(m, MOUNT_FAILURE_START_LIMIT_HIT);
diff --git a/src/core/unit.c b/src/core/unit.c
index c00d30e837..0810bf5a58 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -1729,6 +1729,10 @@ int unit_start(Unit *u) {
assert(u);
+ /* Let's hold off running start jobs for mount units when /proc/self/mountinfo monitor is rate limited. */
+ if (u->type == UNIT_MOUNT && sd_event_source_is_ratelimited(u->manager->mount_event_source))
+ return -EAGAIN;
+
/* If this is already started, then this will succeed. Note that this will even succeed if this unit
* is not startable by the user. This is relied on to detect when we need to wait for units and when
* waiting is finished. */

View File

@ -13,7 +13,7 @@
Name: systemd
Url: http://www.freedesktop.org/wiki/Software/systemd
Version: 239
Release: 59%{?dist}
Release: 60%{?dist}
# For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager
@ -810,6 +810,16 @@ Patch0757: 0757-sd-bus-do-not-read-unused-value.patch
Patch0758: 0758-sd-bus-do-not-return-negative-errno-when-unknown-nam.patch
Patch0759: 0759-sd-bus-switch-to-a-manual-overflow-check-in-sd_bus_t.patch
Patch0760: 0760-resolved-let-s-preferably-route-reverse-lookups-for-.patch
Patch0761: 0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch
Patch0762: 0762-tests-make-inverted-tests-actually-count.patch
Patch0763: 0763-TEST-make-failure-tests-actually-fail-on-failure.patch
Patch0764: 0764-ci-Mergify-configuration-update.patch
Patch0765: 0765-core-propagate-triggered-unit-in-more-load-states.patch
Patch0766: 0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch
Patch0767: 0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch
Patch0768: 0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch
Patch0769: 0769-core-Propagate-condition-failed-state-to-triggering-.patch
Patch0770: 0770-unit-check-for-mount-rate-limiting-before-checking-a.patch
%ifarch %{ix86} x86_64 aarch64
@ -1441,6 +1451,18 @@ fi
%files tests -f .file-list-tests
%changelog
* Thu Jun 23 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-60
- unit: don't emit PropertiesChanged signal if adding a dependency to a unit is a no-op (#1948480)
- tests: make inverted tests actually count (#2087152)
- TEST-*: make failure tests actually fail on failure (#2087152)
- ci(Mergify): configuration update (#2087152)
- core: propagate triggered unit in more load states (#2065322)
- core: propagate unit start limit hit state to triggering path unit (#2065322)
- core: Move 'r' variable declaration to start of unit_start() (#2065322)
- core: Delay start rate limit check when starting a unit (#2065322)
- core: Propagate condition failed state to triggering units. (#2065322)
- unit: check for mount rate limiting before checking active state (#2095744)
* Wed May 18 2022 systemd maintenance team <systemd-maint@redhat.com> - 239-59
- core: disallow using '-.service' as a service name (#2051520)
- shared/dropin: support -.service.d/ top level drop-in for service units (#2051520)