diff --git a/.systemd.metadata b/.systemd.metadata index 8ab9fd3..a883c33 100644 --- a/.systemd.metadata +++ b/.systemd.metadata @@ -1 +1 @@ -249634e3d6b3532f15465719f0437ce04c3eb377 SOURCES/systemd-239.tar.gz +8803baa484cbe36680463c8c5e6febeff074b8e7 SOURCES/systemd-239.tar.gz diff --git a/SOURCES/0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch b/SOURCES/0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch new file mode 100644 index 0000000..90565a6 --- /dev/null +++ b/SOURCES/0761-unit-don-t-emit-PropertiesChanged-signal-if-adding-a.patch @@ -0,0 +1,62 @@ +From a46d3732a4f8baacf1be3e5e0ac152119fe26d4c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= +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; + } + diff --git a/SOURCES/0762-tests-make-inverted-tests-actually-count.patch b/SOURCES/0762-tests-make-inverted-tests-actually-count.patch new file mode 100644 index 0000000..4b7adaa --- /dev/null +++ b/SOURCES/0762-tests-make-inverted-tests-actually-count.patch @@ -0,0 +1,34 @@ +From f784cdd269ccba28e3e14b24ecd33ab9db148403 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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 diff --git a/SOURCES/0763-TEST-make-failure-tests-actually-fail-on-failure.patch b/SOURCES/0763-TEST-make-failure-tests-actually-fail-on-failure.patch new file mode 100644 index 0000000..c2e8e26 --- /dev/null +++ b/SOURCES/0763-TEST-make-failure-tests-actually-fail-on-failure.patch @@ -0,0 +1,123 @@ +From d153f9ff573b191076b843118e825f71227dbc01 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +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 + diff --git a/SOURCES/0764-ci-Mergify-configuration-update.patch b/SOURCES/0764-ci-Mergify-configuration-update.patch new file mode 100644 index 0000000..7d0a006 --- /dev/null +++ b/SOURCES/0764-ci-Mergify-configuration-update.patch @@ -0,0 +1,69 @@ +From cd8518b7f4ebfda9955bf0b649cf759c45e729f1 Mon Sep 17 00:00:00 2001 +From: Jan Macku +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 diff --git a/SOURCES/0765-core-propagate-triggered-unit-in-more-load-states.patch b/SOURCES/0765-core-propagate-triggered-unit-in-more-load-states.patch new file mode 100644 index 0000000..5459390 --- /dev/null +++ b/SOURCES/0765-core-propagate-triggered-unit-in-more-load-states.patch @@ -0,0 +1,122 @@ +From e5121fbb839a36055e5fdab1b9d92dc42f495f29 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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. */ diff --git a/SOURCES/0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch b/SOURCES/0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch new file mode 100644 index 0000000..1cf791d --- /dev/null +++ b/SOURCES/0766-core-propagate-unit-start-limit-hit-state-to-trigger.patch @@ -0,0 +1,68 @@ +From afb5e76925f7f4992252cc392dac4dda6c4faf69 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +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; diff --git a/SOURCES/0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch b/SOURCES/0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch new file mode 100644 index 0000000..1200bd3 --- /dev/null +++ b/SOURCES/0767-core-Move-r-variable-declaration-to-start-of-unit_st.patch @@ -0,0 +1,31 @@ +From 3392b2fb9e4920e9238a09c774252dc0d0183903 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +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; + } diff --git a/SOURCES/0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch b/SOURCES/0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch new file mode 100644 index 0000000..243f795 --- /dev/null +++ b/SOURCES/0768-core-Delay-start-rate-limit-check-when-starting-a-un.patch @@ -0,0 +1,49 @@ +From 8c81776212d0aa44f5ae20635079bd6ce76d16ac Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +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; diff --git a/SOURCES/0769-core-Propagate-condition-failed-state-to-triggering-.patch b/SOURCES/0769-core-Propagate-condition-failed-state-to-triggering-.patch new file mode 100644 index 0000000..14f13a7 --- /dev/null +++ b/SOURCES/0769-core-Propagate-condition-failed-state-to-triggering-.patch @@ -0,0 +1,258 @@ +From 2820f1706275acd787c72d9a57892200566f0bbe Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +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, ...) \ diff --git a/SOURCES/0770-unit-check-for-mount-rate-limiting-before-checking-a.patch b/SOURCES/0770-unit-check-for-mount-rate-limiting-before-checking-a.patch new file mode 100644 index 0000000..eca0afc --- /dev/null +++ b/SOURCES/0770-unit-check-for-mount-rate-limiting-before-checking-a.patch @@ -0,0 +1,52 @@ +From 4dbe6568d5bcc082b13f3ef4d323d1669f16095c Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +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. */ diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index d1db3ff..657a3f4 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -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 - 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 - 239-59 - core: disallow using '-.service' as a service name (#2051520) - shared/dropin: support -.service.d/ top level drop-in for service units (#2051520)