diff --git a/0432-meson-fix-installation-of-ukify.patch b/0432-meson-fix-installation-of-ukify.patch new file mode 100644 index 0000000..20b3ac1 --- /dev/null +++ b/0432-meson-fix-installation-of-ukify.patch @@ -0,0 +1,30 @@ +From a1bd733809ff01c64a8a304a45e57277a5a98463 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 8 Dec 2023 19:35:37 +0100 +Subject: [PATCH] meson: fix installation of ukify + +ln_s was added in upstream later on. It's not present in this branch. +Fixup for b98da2d9e7. + +Related: RHEL-13199 +--- + meson.build | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/meson.build b/meson.build +index 936e612a01..e09c426a72 100644 +--- a/meson.build ++++ b/meson.build +@@ -3868,9 +3868,9 @@ ukify = custom_target( + if want_ukify + public_programs += ukify + +- meson.add_install_script(sh, '-c', +- ln_s.format(bindir / 'ukify', +- rootlibexecdir / 'ukify')) ++ meson.add_install_script(meson_make_symlink, ++ bindir / 'ukify', ++ rootlibexecdir / 'ukify') + endif + + if want_tests != 'false' and want_kernel_install diff --git a/0433-sd-id128-introduce-id128_hash_ops_free.patch b/0433-sd-id128-introduce-id128_hash_ops_free.patch new file mode 100644 index 0000000..64398e9 --- /dev/null +++ b/0433-sd-id128-introduce-id128_hash_ops_free.patch @@ -0,0 +1,37 @@ +From 81802cf297a05d202aae5de21673fcc7064f9b7d Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 28 Oct 2022 09:08:09 +0900 +Subject: [PATCH] sd-id128: introduce id128_hash_ops_free + +(cherry picked from commit 3e61656fab869bb40f019c38c3347885238294de) + +Related: RHEL-5988 +--- + src/libsystemd/sd-id128/id128-util.c | 1 + + src/libsystemd/sd-id128/id128-util.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/src/libsystemd/sd-id128/id128-util.c b/src/libsystemd/sd-id128/id128-util.c +index 4f52c14f64..cef340f3bc 100644 +--- a/src/libsystemd/sd-id128/id128-util.c ++++ b/src/libsystemd/sd-id128/id128-util.c +@@ -184,6 +184,7 @@ sd_id128_t id128_make_v4_uuid(sd_id128_t id) { + } + + DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func); ++DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(id128_hash_ops_free, sd_id128_t, id128_hash_func, id128_compare_func, free); + + int id128_get_product(sd_id128_t *ret) { + sd_id128_t uuid; +diff --git a/src/libsystemd/sd-id128/id128-util.h b/src/libsystemd/sd-id128/id128-util.h +index 17b180c10c..9d8fe93641 100644 +--- a/src/libsystemd/sd-id128/id128-util.h ++++ b/src/libsystemd/sd-id128/id128-util.h +@@ -30,6 +30,7 @@ int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync); + void id128_hash_func(const sd_id128_t *p, struct siphash *state); + int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) _pure_; + extern const struct hash_ops id128_hash_ops; ++extern const struct hash_ops id128_hash_ops_free; + + sd_id128_t id128_make_v4_uuid(sd_id128_t id); + diff --git a/0434-udevadm-trigger-allow-to-fallback-without-synthetic-.patch b/0434-udevadm-trigger-allow-to-fallback-without-synthetic-.patch new file mode 100644 index 0000000..7a0131e --- /dev/null +++ b/0434-udevadm-trigger-allow-to-fallback-without-synthetic-.patch @@ -0,0 +1,104 @@ +From 597c41edd3e94f2c16209359fbd8de7ed44225d7 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 28 Oct 2022 10:14:09 +0900 +Subject: [PATCH] udevadm-trigger: allow to fallback without synthetic UUID + only first time + +If a device is successfully triggered with synthetic UUID, then that means +the kernel support it. Hence, it is not necessary to fallback without UUID +for later devices. + +(cherry picked from commit b15039425feba8f316fb306b75d96e2f0f0b82fa) + +Related: RHEL-5988 +--- + src/udev/udevadm-trigger.c | 22 ++++++++++++++-------- + 1 file changed, 14 insertions(+), 8 deletions(-) + +diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c +index 1d421064d7..cda31edd75 100644 +--- a/src/udev/udevadm-trigger.c ++++ b/src/udev/udevadm-trigger.c +@@ -26,17 +26,20 @@ static bool arg_verbose = false; + static bool arg_dry_run = false; + static bool arg_quiet = false; + static bool arg_uuid = false; ++static bool arg_settle = false; + + static int exec_list( + sd_device_enumerator *e, + sd_device_action_t action, + Hashmap *settle_hashmap) { + +- bool skip_uuid_logic = false; ++ int uuid_supported = -1; + const char *action_str; + sd_device *d; + int r, ret = 0; + ++ assert(e); ++ + action_str = device_action_to_string(action); + + FOREACH_DEVICE_AND_SUBSYSTEM(e, d) { +@@ -57,14 +60,14 @@ static int exec_list( + + /* Use the UUID mode if the user explicitly asked for it, or if --settle has been specified, + * so that we can recognize our own uevent. */ +- r = sd_device_trigger_with_uuid(d, action, (arg_uuid || settle_hashmap) && !skip_uuid_logic ? &id : NULL); +- if (r == -EINVAL && !arg_uuid && settle_hashmap && !skip_uuid_logic) { ++ r = sd_device_trigger_with_uuid(d, action, (arg_uuid || arg_settle) && uuid_supported != 0 ? &id : NULL); ++ if (r == -EINVAL && !arg_uuid && arg_settle && uuid_supported < 0) { + /* If we specified a UUID because of the settling logic, and we got EINVAL this might + * be caused by an old kernel which doesn't know the UUID logic (pre-4.13). Let's try + * if it works without the UUID logic then. */ + r = sd_device_trigger(d, action); + if (r != -EINVAL) +- skip_uuid_logic = true; /* dropping the uuid stuff changed the return code, ++ uuid_supported = false; /* dropping the uuid stuff changed the return code, + * hence don't bother next time */ + } + if (r < 0) { +@@ -108,11 +111,14 @@ static int exec_list( + continue; + } + ++ if (uuid_supported < 0) ++ uuid_supported = true; ++ + /* If the user asked for it, write event UUID to stdout */ + if (arg_uuid) + printf(SD_ID128_UUID_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)); + +- if (settle_hashmap) { ++ if (arg_settle) { + _cleanup_free_ sd_id128_t *mid = NULL; + _cleanup_free_ char *sp = NULL; + +@@ -285,7 +291,7 @@ int trigger_main(int argc, char *argv[], void *userdata) { + _cleanup_(sd_event_unrefp) sd_event *event = NULL; + _cleanup_hashmap_free_ Hashmap *settle_hashmap = NULL; + usec_t ping_timeout_usec = 5 * USEC_PER_SEC; +- bool settle = false, ping = false; ++ bool ping = false; + int c, r; + + if (running_in_chroot() > 0) { +@@ -389,7 +395,7 @@ int trigger_main(int argc, char *argv[], void *userdata) { + break; + } + case 'w': +- settle = true; ++ arg_settle = true; + break; + + case ARG_NAME: { +@@ -477,7 +483,7 @@ int trigger_main(int argc, char *argv[], void *userdata) { + return log_error_errno(r, "Failed to add parent match '%s': %m", argv[optind]); + } + +- if (settle) { ++ if (arg_settle) { + settle_hashmap = hashmap_new(&path_hash_ops_free_free); + if (!settle_hashmap) + return log_oom(); diff --git a/0435-udevadm-trigger-settle-with-synthetic-UUID-if-the-ke.patch b/0435-udevadm-trigger-settle-with-synthetic-UUID-if-the-ke.patch new file mode 100644 index 0000000..e31953e --- /dev/null +++ b/0435-udevadm-trigger-settle-with-synthetic-UUID-if-the-ke.patch @@ -0,0 +1,196 @@ +From 73dbfdaab1d633e3a1ae96cc15c551eaa2fd4243 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 28 Oct 2022 10:21:57 +0900 +Subject: [PATCH] udevadm-trigger: settle with synthetic UUID if the kernel + support it + +If the kernel support synthetic UUID in uevent, then let's assume that +the UUID is unique, and check only if the received UUID matches we +specified. + +Partially fixes #25115. + +(cherry picked from commit dfbd824a0b780310d7f865a6ea0d60434d924683) + +Related: RHEL-5988 +--- + src/udev/udevadm-trigger.c | 82 +++++++++++++++++++------------------- + 1 file changed, 40 insertions(+), 42 deletions(-) + +diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c +index cda31edd75..3909fa237c 100644 +--- a/src/udev/udevadm-trigger.c ++++ b/src/udev/udevadm-trigger.c +@@ -11,10 +11,12 @@ + #include "device-util.h" + #include "fd-util.h" + #include "fileio.h" ++#include "id128-util.h" + #include "parse-util.h" + #include "path-util.h" + #include "process-util.h" + #include "set.h" ++#include "static-destruct.h" + #include "string-util.h" + #include "strv.h" + #include "udevadm.h" +@@ -31,8 +33,9 @@ static bool arg_settle = false; + static int exec_list( + sd_device_enumerator *e, + sd_device_action_t action, +- Hashmap *settle_hashmap) { ++ Set **ret_settle_path_or_ids) { + ++ _cleanup_set_free_ Set *settle_path_or_ids = NULL; + int uuid_supported = -1; + const char *action_str; + sd_device *d; +@@ -119,60 +122,62 @@ static int exec_list( + printf(SD_ID128_UUID_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)); + + if (arg_settle) { +- _cleanup_free_ sd_id128_t *mid = NULL; +- _cleanup_free_ char *sp = NULL; ++ if (uuid_supported) { ++ sd_id128_t *dup; + +- sp = strdup(syspath); +- if (!sp) +- return log_oom(); ++ dup = newdup(sd_id128_t, &id, 1); ++ if (!dup) ++ return log_oom(); + +- mid = newdup(sd_id128_t, &id, 1); +- if (!d) +- return log_oom(); ++ r = set_ensure_consume(&settle_path_or_ids, &id128_hash_ops_free, dup); ++ } else { ++ char *dup; ++ ++ dup = strdup(syspath); ++ if (!dup) ++ return log_oom(); + +- r = hashmap_put(settle_hashmap, sp, mid); ++ r = set_ensure_consume(&settle_path_or_ids, &path_hash_ops_free, dup); ++ } + if (r < 0) + return log_oom(); +- +- TAKE_PTR(sp); +- TAKE_PTR(mid); + } + } + ++ if (ret_settle_path_or_ids) ++ *ret_settle_path_or_ids = TAKE_PTR(settle_path_or_ids); ++ + return ret; + } + + static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *userdata) { +- Hashmap *settle_hashmap = ASSERT_PTR(userdata); +- sd_id128_t *settle_id; ++ Set *settle_path_or_ids = * (Set**) ASSERT_PTR(userdata); + const char *syspath; +- char *k; ++ sd_id128_t id; + int r; + + assert(dev); + + r = sd_device_get_syspath(dev, &syspath); + if (r < 0) { +- log_debug_errno(r, "Failed to get syspath of device event, ignoring: %m"); ++ log_device_debug_errno(dev, r, "Failed to get syspath of device event, ignoring: %m"); + return 0; + } + +- settle_id = hashmap_get2(settle_hashmap, syspath, (void**) &k); +- if (!settle_id) { +- log_debug("Got uevent for unexpected device '%s', ignoring.", syspath); +- return 0; +- } +- if (!sd_id128_is_null(*settle_id)) { /* If this is SD_ID128_NULL then we are on pre-4.13 and have no UUID to check, hence don't */ +- sd_id128_t event_id; ++ if (sd_device_get_trigger_uuid(dev, &id) >= 0) { ++ _cleanup_free_ sd_id128_t *saved = NULL; + +- r = sd_device_get_trigger_uuid(dev, &event_id); +- if (r < 0) { +- log_debug_errno(r, "Got uevent without synthetic UUID for device '%s', ignoring: %m", syspath); ++ saved = set_remove(settle_path_or_ids, &id); ++ if (!saved) { ++ log_device_debug(dev, "Got uevent not matching expected UUID, ignoring."); + return 0; + } ++ } else { ++ _cleanup_free_ char *saved = NULL; + +- if (!sd_id128_equal(event_id, *settle_id)) { +- log_debug("Got uevent not matching expected UUID for device '%s', ignoring.", syspath); ++ saved = set_remove(settle_path_or_ids, syspath); ++ if (!saved) { ++ log_device_debug(dev, "Got uevent for unexpected device, ignoring."); + return 0; + } + } +@@ -181,12 +186,9 @@ static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *us + printf("settle %s\n", syspath); + + if (arg_uuid) +- printf("settle " SD_ID128_UUID_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(*settle_id)); ++ printf("settle " SD_ID128_UUID_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(id)); + +- free(hashmap_remove(settle_hashmap, syspath)); +- free(k); +- +- if (hashmap_isempty(settle_hashmap)) ++ if (set_isempty(settle_path_or_ids)) + return sd_event_exit(sd_device_monitor_get_event(m), 0); + + return 0; +@@ -289,7 +291,7 @@ int trigger_main(int argc, char *argv[], void *userdata) { + _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *m = NULL; + _cleanup_(sd_event_unrefp) sd_event *event = NULL; +- _cleanup_hashmap_free_ Hashmap *settle_hashmap = NULL; ++ _cleanup_set_free_ Set *settle_path_or_ids = NULL; + usec_t ping_timeout_usec = 5 * USEC_PER_SEC; + bool ping = false; + int c, r; +@@ -484,10 +486,6 @@ int trigger_main(int argc, char *argv[], void *userdata) { + } + + if (arg_settle) { +- settle_hashmap = hashmap_new(&path_hash_ops_free_free); +- if (!settle_hashmap) +- return log_oom(); +- + r = sd_event_default(&event); + if (r < 0) + return log_error_errno(r, "Failed to get default event: %m"); +@@ -500,7 +498,7 @@ int trigger_main(int argc, char *argv[], void *userdata) { + if (r < 0) + return log_error_errno(r, "Failed to attach event to device monitor: %m"); + +- r = sd_device_monitor_start(m, device_monitor_handler, settle_hashmap); ++ r = sd_device_monitor_start(m, device_monitor_handler, &settle_path_or_ids); + if (r < 0) + return log_error_errno(r, "Failed to start device monitor: %m"); + } +@@ -525,11 +523,11 @@ int trigger_main(int argc, char *argv[], void *userdata) { + assert_not_reached(); + } + +- r = exec_list(e, action, settle_hashmap); ++ r = exec_list(e, action, arg_settle ? &settle_path_or_ids : NULL); + if (r < 0) + return r; + +- if (event && !hashmap_isempty(settle_hashmap)) { ++ if (!set_isempty(settle_path_or_ids)) { + r = sd_event_loop(event); + if (r < 0) + return log_error_errno(r, "Event loop failed: %m"); diff --git a/0436-udevadm-trigger-also-check-with-the-original-syspath.patch b/0436-udevadm-trigger-also-check-with-the-original-syspath.patch new file mode 100644 index 0000000..919a50b --- /dev/null +++ b/0436-udevadm-trigger-also-check-with-the-original-syspath.patch @@ -0,0 +1,56 @@ +From 4007f494b2e4c45f2d59948af3f4053258d3f127 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 28 Oct 2022 09:06:02 +0900 +Subject: [PATCH] udevadm-trigger: also check with the original syspath if + device is renamed + +For older kernels that synthetic UUID is not supported, we need to also +check the original device name, as udevd broadcasts uevent with new +sysname. + +Fixes #25115. + +(cherry picked from commit 1193448cb68e5a90cab027e16a093bbd367e9494) + +Related: RHEL-5988 +--- + src/udev/udevadm-trigger.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c +index 3909fa237c..40ee5085a0 100644 +--- a/src/udev/udevadm-trigger.c ++++ b/src/udev/udevadm-trigger.c +@@ -176,6 +176,32 @@ static int device_monitor_handler(sd_device_monitor *m, sd_device *dev, void *us + _cleanup_free_ char *saved = NULL; + + saved = set_remove(settle_path_or_ids, syspath); ++ if (!saved) { ++ const char *old_sysname; ++ ++ /* When the device is renamed, the new name is broadcast, and the old name is saved ++ * in INTERFACE_OLD. */ ++ ++ if (sd_device_get_property_value(dev, "INTERFACE_OLD", &old_sysname) >= 0) { ++ _cleanup_free_ char *dir = NULL, *old_syspath = NULL; ++ ++ r = path_extract_directory(syspath, &dir); ++ if (r < 0) { ++ log_device_debug_errno(dev, r, ++ "Failed to extract directory from '%s', ignoring: %m", ++ syspath); ++ return 0; ++ } ++ ++ old_syspath = path_join(dir, old_sysname); ++ if (!old_syspath) { ++ log_oom_debug(); ++ return 0; ++ } ++ ++ saved = set_remove(settle_path_or_ids, old_syspath); ++ } ++ } + if (!saved) { + log_device_debug(dev, "Got uevent for unexpected device, ignoring."); + return 0; diff --git a/0437-test-use-udevadm-trigger-settle-even-if-device-is-re.patch b/0437-test-use-udevadm-trigger-settle-even-if-device-is-re.patch new file mode 100644 index 0000000..ed90733 --- /dev/null +++ b/0437-test-use-udevadm-trigger-settle-even-if-device-is-re.patch @@ -0,0 +1,37 @@ +From ff755f035485eab0317d1320caa2748d5d4a2d78 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 27 Oct 2022 05:48:05 +0900 +Subject: [PATCH] test: use 'udevadm trigger --settle' even if device is + renamed + +(cherry picked from commit ff4d2a09fd141474cb552d4b5bd5a53d9748a1b4) + +Related: RHEL-5988 +--- + test/units/testsuite-17.02.sh | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/test/units/testsuite-17.02.sh b/test/units/testsuite-17.02.sh +index ed3b39d074..82f9fd1f62 100755 +--- a/test/units/testsuite-17.02.sh ++++ b/test/units/testsuite-17.02.sh +@@ -61,9 +61,7 @@ EOF + + udevadm control --log-priority=debug --reload --timeout=30 + +-# FIXME(?): the 'add' uevent is broadcast as for 'foobar', instead of 'hoge'. Hence, we cannot use --settle here. +-# See issue #25115. +-udevadm trigger --action=add /sys/devices/virtual/net/hoge ++udevadm trigger --action=add --settle /sys/devices/virtual/net/hoge + udevadm wait --timeout=30 --settle /sys/devices/virtual/net/foobar + assert_not_in "ID_RENAMING=" "$(udevadm info /sys/devices/virtual/net/foobar)" + timeout 30 bash -c 'while [[ "$(systemctl show --property=ActiveState --value /sys/devices/virtual/net/hoge)" != "inactive" ]]; do sleep .5; done' +@@ -71,7 +69,7 @@ timeout 30 bash -c 'while [[ "$(systemctl show --property=ActiveState --value /s + timeout 30 bash -c 'while [[ "$(systemctl show --property=ActiveState --value /sys/devices/virtual/net/foobar)" != "active" ]]; do sleep .5; done' + timeout 30 bash -c 'while [[ "$(systemctl show --property=ActiveState --value /sys/subsystem/net/devices/foobar)" != "active" ]]; do sleep .5; done' + +-udevadm trigger --action=add /sys/devices/virtual/net/foobar ++udevadm trigger --action=add --settle /sys/devices/virtual/net/foobar + udevadm wait --timeout=30 --settle /sys/devices/virtual/net/hoge + assert_not_in "ID_RENAMING=" "$(udevadm info /sys/devices/virtual/net/hoge)" + timeout 30 bash -c 'while [[ "$(systemctl show --property=ActiveState --value /sys/devices/virtual/net/hoge)" != "active" ]]; do sleep .5; done' diff --git a/0438-sd-event-don-t-mistake-USEC_INFINITY-passed-in-for-o.patch b/0438-sd-event-don-t-mistake-USEC_INFINITY-passed-in-for-o.patch new file mode 100644 index 0000000..8c0ecc7 --- /dev/null +++ b/0438-sd-event-don-t-mistake-USEC_INFINITY-passed-in-for-o.patch @@ -0,0 +1,33 @@ +From e92c85b68932845c908cb3f38b2130c57065e263 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 6 Jan 2023 11:27:17 +0100 +Subject: [PATCH] sd-event: don't mistake USEC_INFINITY passed in for overflow + +Let's pass USEC_INFINITY from sd_event_source_set_time_relative() to +sd_event_source_set_time() instead of raising EOVERFLOW. + +We should raise EOVERFLOW only if your addition fails, but not if the +input already is USEC_INFINITY, since it's an entirely valid operation +to have an infinite time-out, and we should support that. + +(cherry picked from commit ef8591951aefccb668201f24aa481aa6cda834da) + +Related: RHEL-6090 +--- + src/libsystemd/sd-event/sd-event.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 778070a5fb..cd73cd8bfd 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -2723,6 +2723,9 @@ _public_ int sd_event_source_set_time_relative(sd_event_source *s, uint64_t usec + assert_return(s, -EINVAL); + assert_return(EVENT_SOURCE_IS_TIME(s->type), -EDOM); + ++ if (usec == USEC_INFINITY) ++ return sd_event_source_set_time(s, USEC_INFINITY); ++ + r = sd_event_now(s->event, event_source_type_to_clock(s->type), &t); + if (r < 0) + return r; diff --git a/0439-pid1-rework-service_arm_timer-to-optionally-take-a-r.patch b/0439-pid1-rework-service_arm_timer-to-optionally-take-a-r.patch new file mode 100644 index 0000000..690b878 --- /dev/null +++ b/0439-pid1-rework-service_arm_timer-to-optionally-take-a-r.patch @@ -0,0 +1,118 @@ +From 917b03f2b5ccdd668a49da7df72baaddd338c071 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 15:06:10 +0100 +Subject: [PATCH] pid1: rework service_arm_timer() to optionally take a + relative time value + +In most cases this is actually what we want, hence simplify this case. + +(cherry picked from commit e5d6dcce7f852b978251d062afb2fcba16714eb9) + +Related: RHEL-6090 +--- + src/core/service.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 1e14cdc6ca..aa76b4ad9a 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -530,13 +530,13 @@ static usec_t service_running_timeout(Service *s) { + delta); + } + +-static int service_arm_timer(Service *s, usec_t usec) { ++static int service_arm_timer(Service *s, bool relative, usec_t usec) { + int r; + + assert(s); + + if (s->timer_event_source) { +- r = sd_event_source_set_time(s->timer_event_source, usec); ++ r = (relative ? sd_event_source_set_time_relative : sd_event_source_set_time)(s->timer_event_source, usec); + if (r < 0) + return r; + +@@ -546,7 +546,7 @@ static int service_arm_timer(Service *s, usec_t usec) { + if (usec == USEC_INFINITY) + return 0; + +- r = sd_event_add_time( ++ r = (relative ? sd_event_add_time_relative : sd_event_add_time)( + UNIT(s)->manager->event, + &s->timer_event_source, + CLOCK_MONOTONIC, +@@ -1195,7 +1195,7 @@ static int service_coldplug(Unit *u) { + if (s->deserialized_state == s->state) + return 0; + +- r = service_arm_timer(s, service_coldplug_timeout(s)); ++ r = service_arm_timer(s, /* relative= */ false, service_coldplug_timeout(s)); + if (r < 0) + return r; + +@@ -1538,7 +1538,7 @@ static int service_spawn_internal( + return r; + } + +- r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), timeout)); ++ r = service_arm_timer(s, /* relative= */ true, timeout); + if (r < 0) + return r; + +@@ -1857,7 +1857,7 @@ static void service_enter_dead(Service *s, ServiceResult f, bool allow_restart) + if (s->will_auto_restart) { + s->will_auto_restart = false; + +- r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->restart_usec)); ++ r = service_arm_timer(s, /* relative= */ true, s->restart_usec); + if (r < 0) { + s->n_keep_fd_store--; + goto fail; +@@ -1989,8 +1989,8 @@ static void service_enter_signal(Service *s, ServiceState state, ServiceResult f + goto fail; + + if (r > 0) { +- r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), +- kill_operation == KILL_WATCHDOG ? service_timeout_abort_usec(s) : s->timeout_stop_usec)); ++ r = service_arm_timer(s, /* relative= */ true, ++ kill_operation == KILL_WATCHDOG ? service_timeout_abort_usec(s) : s->timeout_stop_usec); + if (r < 0) + goto fail; + +@@ -2020,7 +2020,7 @@ static void service_enter_stop_by_notify(Service *s) { + + (void) unit_enqueue_rewatch_pids(UNIT(s)); + +- service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec)); ++ service_arm_timer(s, /* relative= */ true, s->timeout_stop_usec); + + /* The service told us it's stopping, so it's as if we SIGTERM'd it. */ + service_set_state(s, SERVICE_STOP_SIGTERM); +@@ -2099,7 +2099,7 @@ static void service_enter_running(Service *s, ServiceResult f) { + service_enter_stop_by_notify(s); + else { + service_set_state(s, SERVICE_RUNNING); +- service_arm_timer(s, service_running_timeout(s)); ++ service_arm_timer(s, /* relative= */ false, service_running_timeout(s)); + } + + } else if (s->remain_after_exit) +@@ -2398,7 +2398,7 @@ static void service_enter_reload_by_notify(Service *s) { + + assert(s); + +- service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_start_usec)); ++ service_arm_timer(s, /* relative= */ true, s->timeout_start_usec); + service_set_state(s, SERVICE_RELOAD); + + /* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */ +@@ -4570,7 +4570,7 @@ static int service_clean(Unit *u, ExecCleanMask mask) { + s->control_command = NULL; + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; + +- r = service_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->exec_context.timeout_clean_usec)); ++ r = service_arm_timer(s, /* relative= */ true, s->exec_context.timeout_clean_usec); + if (r < 0) + goto fail; + diff --git a/0440-manager-add-one-more-assert.patch b/0440-manager-add-one-more-assert.patch new file mode 100644 index 0000000..b9c3c9f --- /dev/null +++ b/0440-manager-add-one-more-assert.patch @@ -0,0 +1,25 @@ +From efe1737efae0950b7ded32d9c5e1a9cfaea7296b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 15:00:05 +0100 +Subject: [PATCH] manager: add one more assert() + +(cherry picked from commit 7fa49280bc33ba5135228401fb24dce0de5f9195) + +Related: RHEL-6090 +--- + src/core/manager.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 657263eb73..6371810ce3 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -806,6 +806,8 @@ static int manager_find_credentials_dirs(Manager *m) { + } + + void manager_set_switching_root(Manager *m, bool switching_root) { ++ assert(m); ++ + m->switching_root = MANAGER_IS_SYSTEM(m) && switching_root; + } + diff --git a/0441-pid1-add-new-Type-notify-reload-service-type.patch b/0441-pid1-add-new-Type-notify-reload-service-type.patch new file mode 100644 index 0000000..a0aa911 --- /dev/null +++ b/0441-pid1-add-new-Type-notify-reload-service-type.patch @@ -0,0 +1,688 @@ +From f64d331351e33199c4096b2ae4a4b9d24d127661 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 16:49:23 +0100 +Subject: [PATCH] pid1: add new Type=notify-reload service type + +Fixes: #6162 +(cherry picked from commit 3bd28bf721dc70722ff1c675026ed0b44ad968a3) + +Resolves: RHEL-6090 +--- + man/org.freedesktop.systemd1.xml | 6 + + src/basic/unit-def.c | 2 + + src/basic/unit-def.h | 4 +- + src/core/dbus-service.c | 5 + + src/core/load-fragment-gperf.gperf.in | 1 + + src/core/service.c | 226 ++++++++++++++++++-------- + src/core/service.h | 18 +- + src/shared/bus-unit-util.c | 3 +- + 8 files changed, 189 insertions(+), 76 deletions(-) + +diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml +index 13a84af747..c18428a092 100644 +--- a/man/org.freedesktop.systemd1.xml ++++ b/man/org.freedesktop.systemd1.xml +@@ -2570,6 +2570,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + readonly u NRestarts = ...; + @org.freedesktop.DBus.Property.EmitsChangedSignal("const") + readonly s OOMPolicy = '...'; ++ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") ++ readonly i ReloadSignal = ...; + readonly t ExecMainStartTimestamp = ...; + readonly t ExecMainStartTimestampMonotonic = ...; + readonly t ExecMainExitTimestamp = ...; +@@ -3163,6 +3165,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + ++ ++ + + + +@@ -3715,6 +3719,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice { + + + ++ ++ + + + +diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c +index 94cd603e32..bdb1860246 100644 +--- a/src/basic/unit-def.c ++++ b/src/basic/unit-def.c +@@ -188,6 +188,8 @@ static const char* const service_state_table[_SERVICE_STATE_MAX] = { + [SERVICE_RUNNING] = "running", + [SERVICE_EXITED] = "exited", + [SERVICE_RELOAD] = "reload", ++ [SERVICE_RELOAD_SIGNAL] = "reload-signal", ++ [SERVICE_RELOAD_NOTIFY] = "reload-notify", + [SERVICE_STOP] = "stop", + [SERVICE_STOP_WATCHDOG] = "stop-watchdog", + [SERVICE_STOP_SIGTERM] = "stop-sigterm", +diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h +index 5fcd51c095..bae132ea09 100644 +--- a/src/basic/unit-def.h ++++ b/src/basic/unit-def.h +@@ -132,7 +132,9 @@ typedef enum ServiceState { + SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_EXITED, /* Nothing is running anymore, but RemainAfterExit is true hence this is OK */ +- SERVICE_RELOAD, ++ SERVICE_RELOAD, /* Reloading via ExecReload= */ ++ SERVICE_RELOAD_SIGNAL, /* Reloading via SIGHUP requested */ ++ SERVICE_RELOAD_NOTIFY, /* Waiting for READY=1 after RELOADING=1 notify */ + SERVICE_STOP, /* No STOP_PRE state, instead just register multiple STOP executables */ + SERVICE_STOP_WATCHDOG, + SERVICE_STOP_SIGTERM, +diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c +index 6e4bc0bd1a..3d130db66a 100644 +--- a/src/core/dbus-service.c ++++ b/src/core/dbus-service.c +@@ -228,6 +228,7 @@ const sd_bus_vtable bus_service_vtable[] = { + SD_BUS_PROPERTY("GID", "u", bus_property_get_gid, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("OOMPolicy", "s", bus_property_get_oom_policy, offsetof(Service, oom_policy), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("ReloadSignal", "i", bus_property_get_int, offsetof(Service, reload_signal), SD_BUS_VTABLE_PROPERTY_CONST), + + BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecCondition", offsetof(Service, exec_command[SERVICE_EXEC_CONDITION]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), +@@ -374,6 +375,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_r + static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string); + static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid); + static BUS_DEFINE_SET_TRANSIENT_PARSE(timeout_failure_mode, ServiceTimeoutFailureMode, service_timeout_failure_mode_from_string); ++static BUS_DEFINE_SET_TRANSIENT_TO_STRING(reload_signal, "i", int32_t, int, "%" PRIi32, signal_to_string_with_check); + + static int bus_service_set_transient_property( + Service *s, +@@ -532,6 +534,9 @@ static int bus_service_set_transient_property( + if (streq(name, "StandardErrorFileDescriptor")) + return bus_set_transient_std_fd(u, name, &s->stderr_fd, &s->exec_context.stdio_as_fds, message, flags, error); + ++ if (streq(name, "ReloadSignal")) ++ return bus_set_transient_reload_signal(u, name, &s->reload_signal, message, flags, error); ++ + return 0; + } + +diff --git a/src/core/load-fragment-gperf.gperf.in b/src/core/load-fragment-gperf.gperf.in +index 81a5971339..53089d5590 100644 +--- a/src/core/load-fragment-gperf.gperf.in ++++ b/src/core/load-fragment-gperf.gperf.in +@@ -424,6 +424,7 @@ Service.BusPolicy, config_parse_warn_compat, + Service.USBFunctionDescriptors, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_descriptors) + Service.USBFunctionStrings, config_parse_unit_path_printf, 0, offsetof(Service, usb_function_strings) + Service.OOMPolicy, config_parse_oom_policy, 0, offsetof(Service, oom_policy) ++Service.ReloadSignal, config_parse_signal, 0, offsetof(Service, reload_signal) + {{ EXEC_CONTEXT_CONFIG_ITEMS('Service') }} + {{ CGROUP_CONTEXT_CONFIG_ITEMS('Service') }} + {{ KILL_CONTEXT_CONFIG_ITEMS('Service') }} +diff --git a/src/core/service.c b/src/core/service.c +index aa76b4ad9a..902948905f 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -54,6 +54,8 @@ static const UnitActiveState state_translation_table[_SERVICE_STATE_MAX] = { + [SERVICE_RUNNING] = UNIT_ACTIVE, + [SERVICE_EXITED] = UNIT_ACTIVE, + [SERVICE_RELOAD] = UNIT_RELOADING, ++ [SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING, ++ [SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING, + [SERVICE_STOP] = UNIT_DEACTIVATING, + [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING, + [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, +@@ -78,6 +80,8 @@ static const UnitActiveState state_translation_table_idle[_SERVICE_STATE_MAX] = + [SERVICE_RUNNING] = UNIT_ACTIVE, + [SERVICE_EXITED] = UNIT_ACTIVE, + [SERVICE_RELOAD] = UNIT_RELOADING, ++ [SERVICE_RELOAD_SIGNAL] = UNIT_RELOADING, ++ [SERVICE_RELOAD_NOTIFY] = UNIT_RELOADING, + [SERVICE_STOP] = UNIT_DEACTIVATING, + [SERVICE_STOP_WATCHDOG] = UNIT_DEACTIVATING, + [SERVICE_STOP_SIGTERM] = UNIT_DEACTIVATING, +@@ -124,6 +128,8 @@ static void service_init(Unit *u) { + s->watchdog_original_usec = USEC_INFINITY; + + s->oom_policy = _OOM_POLICY_INVALID; ++ s->reload_begin_usec = USEC_INFINITY; ++ s->reload_signal = SIGHUP; + } + + static void service_unwatch_control_pid(Service *s) { +@@ -765,7 +771,7 @@ static int service_add_extras(Service *s) { + + /* If the service needs the notify socket, let's enable it automatically. */ + if (s->notify_access == NOTIFY_NONE && +- (s->type == SERVICE_NOTIFY || s->watchdog_usec > 0 || s->n_fd_store_max > 0)) ++ (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) || s->watchdog_usec > 0 || s->n_fd_store_max > 0)) + s->notify_access = NOTIFY_MAIN; + + /* If no OOM policy was explicitly set, then default to the configure default OOM policy. Except when +@@ -830,7 +836,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { + "%sRestart: %s\n" + "%sNotifyAccess: %s\n" + "%sNotifyState: %s\n" +- "%sOOMPolicy: %s\n", ++ "%sOOMPolicy: %s\n" ++ "%sReloadSignal: %s\n", + prefix, service_state_to_string(s->state), + prefix, service_result_to_string(s->result), + prefix, service_result_to_string(s->reload_result), +@@ -843,7 +850,8 @@ static void service_dump(Unit *u, FILE *f, const char *prefix) { + prefix, service_restart_to_string(s->restart), + prefix, notify_access_to_string(s->notify_access), + prefix, notify_state_to_string(s->notify_state), +- prefix, oom_policy_to_string(s->oom_policy)); ++ prefix, oom_policy_to_string(s->oom_policy), ++ prefix, signal_to_string(s->reload_signal)); + + if (s->control_pid > 0) + fprintf(f, +@@ -1088,7 +1096,7 @@ static void service_set_state(Service *s, ServiceState state) { + if (!IN_SET(state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, + SERVICE_RUNNING, +- SERVICE_RELOAD, ++ SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_AUTO_RESTART, +@@ -1097,7 +1105,8 @@ static void service_set_state(Service *s, ServiceState state) { + + if (!IN_SET(state, + SERVICE_START, SERVICE_START_POST, +- SERVICE_RUNNING, SERVICE_RELOAD, ++ SERVICE_RUNNING, ++ SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL)) { + service_unwatch_main_pid(s); +@@ -1106,7 +1115,7 @@ static void service_set_state(Service *s, ServiceState state) { + + if (!IN_SET(state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, +- SERVICE_RELOAD, ++ SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_CLEANING)) { +@@ -1122,7 +1131,8 @@ static void service_set_state(Service *s, ServiceState state) { + + if (!IN_SET(state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, +- SERVICE_RUNNING, SERVICE_RELOAD, ++ SERVICE_RUNNING, ++ SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL) && + !(state == SERVICE_DEAD && UNIT(s)->job)) +@@ -1131,7 +1141,7 @@ static void service_set_state(Service *s, ServiceState state) { + if (state != SERVICE_START) + s->exec_fd_event_source = sd_event_source_disable_unref(s->exec_fd_event_source); + +- if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) ++ if (!IN_SET(state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY)) + service_stop_watchdog(s); + + /* For the inactive states unit_notify() will trim the cgroup, +@@ -1157,6 +1167,8 @@ static usec_t service_coldplug_timeout(Service *s) { + case SERVICE_START: + case SERVICE_START_POST: + case SERVICE_RELOAD: ++ case SERVICE_RELOAD_SIGNAL: ++ case SERVICE_RELOAD_NOTIFY: + return usec_add(UNIT(s)->state_change_timestamp.monotonic, s->timeout_start_usec); + + case SERVICE_RUNNING: +@@ -1203,7 +1215,8 @@ static int service_coldplug(Unit *u) { + pid_is_unwaited(s->main_pid) && + (IN_SET(s->deserialized_state, + SERVICE_START, SERVICE_START_POST, +- SERVICE_RUNNING, SERVICE_RELOAD, ++ SERVICE_RUNNING, ++ SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL))) { + r = unit_watch_pid(UNIT(s), s->main_pid, false); +@@ -1215,7 +1228,7 @@ static int service_coldplug(Unit *u) { + pid_is_unwaited(s->control_pid) && + IN_SET(s->deserialized_state, + SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, +- SERVICE_RELOAD, ++ SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, SERVICE_STOP_WATCHDOG, SERVICE_STOP_SIGTERM, SERVICE_STOP_SIGKILL, SERVICE_STOP_POST, + SERVICE_FINAL_WATCHDOG, SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL, + SERVICE_CLEANING)) { +@@ -1230,7 +1243,7 @@ static int service_coldplug(Unit *u) { + (void) unit_setup_exec_runtime(u); + } + +- if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) ++ if (IN_SET(s->deserialized_state, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY)) + service_start_watchdog(s); + + if (UNIT_ISSET(s->accept_socket)) { +@@ -2255,7 +2268,7 @@ static void service_enter_start(Service *s) { + s->control_pid = pid; + service_set_state(s, SERVICE_START); + +- } else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_EXEC)) { ++ } else if (IN_SET(s->type, SERVICE_ONESHOT, SERVICE_DBUS, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD, SERVICE_EXEC)) { + + /* For oneshot services we wait until the start process exited, too, but it is our main process. */ + +@@ -2399,7 +2412,7 @@ static void service_enter_reload_by_notify(Service *s) { + assert(s); + + service_arm_timer(s, /* relative= */ true, s->timeout_start_usec); +- service_set_state(s, SERVICE_RELOAD); ++ service_set_state(s, SERVICE_RELOAD_NOTIFY); + + /* service_enter_reload_by_notify is never called during a reload, thus no loops are possible. */ + r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); +@@ -2408,6 +2421,7 @@ static void service_enter_reload_by_notify(Service *s) { + } + + static void service_enter_reload(Service *s) { ++ bool killed = false; + int r; + + assert(s); +@@ -2415,6 +2429,18 @@ static void service_enter_reload(Service *s) { + service_unwatch_control_pid(s); + s->reload_result = SERVICE_SUCCESS; + ++ usec_t ts = now(CLOCK_MONOTONIC); ++ ++ if (s->type == SERVICE_NOTIFY_RELOAD && s->main_pid > 0) { ++ r = kill_and_sigcont(s->main_pid, s->reload_signal); ++ if (r < 0) { ++ log_unit_warning_errno(UNIT(s), r, "Failed to send reload signal: %m"); ++ goto fail; ++ } ++ ++ killed = true; ++ } ++ + s->control_command = s->exec_command[SERVICE_EXEC_RELOAD]; + if (s->control_command) { + s->control_command_id = SERVICE_EXEC_RELOAD; +@@ -2424,17 +2450,28 @@ static void service_enter_reload(Service *s) { + s->timeout_start_usec, + EXEC_APPLY_SANDBOXING|EXEC_APPLY_CHROOT|EXEC_IS_CONTROL|EXEC_CONTROL_CGROUP, + &s->control_pid); +- if (r < 0) ++ if (r < 0) { ++ log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m"); + goto fail; ++ } + + service_set_state(s, SERVICE_RELOAD); +- } else ++ } else if (killed) { ++ service_arm_timer(s, /* relative= */ true, s->timeout_start_usec); ++ service_set_state(s, SERVICE_RELOAD_SIGNAL); ++ } else { + service_enter_running(s, SERVICE_SUCCESS); ++ return; ++ } + ++ /* Store the timestamp when we started reloading: when reloading via SIGHUP we won't leave the reload ++ * state until we received both RELOADING=1 and READY=1 with MONOTONIC_USEC= set to a value above ++ * this. Thus we know for sure the reload cycle was executed *after* we requested it, and is not one ++ * that was already in progress before. */ ++ s->reload_begin_usec = ts; + return; + + fail: +- log_unit_warning_errno(UNIT(s), r, "Failed to run 'reload' task: %m"); + s->reload_result = SERVICE_FAILURE_RESOURCES; + service_enter_running(s, SERVICE_SUCCESS); + } +@@ -2597,9 +2634,8 @@ static int service_stop(Unit *u) { + return 0; + } + +- /* If there's already something running we go directly into +- * kill mode. */ +- if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_STOP_WATCHDOG)) { ++ /* If there's already something running we go directly into kill mode. */ ++ if (IN_SET(s->state, SERVICE_CONDITION, SERVICE_START_PRE, SERVICE_START, SERVICE_START_POST, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY, SERVICE_STOP_WATCHDOG)) { + service_enter_signal(s, SERVICE_STOP_SIGTERM, SERVICE_SUCCESS); + return 0; + } +@@ -2632,7 +2668,8 @@ _pure_ static bool service_can_reload(Unit *u) { + + assert(s); + +- return !!s->exec_command[SERVICE_EXEC_RELOAD]; ++ return s->exec_command[SERVICE_EXEC_RELOAD] || ++ s->type == SERVICE_NOTIFY_RELOAD; + } + + static unsigned service_exec_command_index(Unit *u, ServiceExecCommand id, ExecCommand *current) { +@@ -2808,6 +2845,9 @@ static int service_serialize(Unit *u, FILE *f, FDSet *fds) { + if (s->watchdog_original_usec != USEC_INFINITY) + (void) serialize_item_format(f, "watchdog-original-usec", USEC_FMT, s->watchdog_original_usec); + ++ if (s->reload_begin_usec != USEC_INFINITY) ++ (void) serialize_item_format(f, "reload-begin-usec", USEC_FMT, s->reload_begin_usec); ++ + return 0; + } + +@@ -3146,6 +3186,10 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value, + log_unit_debug_errno(u, r, "Failed to parse serialized flush restart counter setting '%s': %m", value); + else + s->flush_n_restarts = r; ++ } else if (streq(key, "reload-begin-usec")) { ++ r = deserialize_usec(value, &s->reload_begin_usec); ++ if (r < 0) ++ log_unit_debug_errno(u, r, "Failed to parse serialized reload begin timestamp '%s', ignoring: %m", value); + } else + log_unit_debug(u, "Unknown serialization key: %s", key); + +@@ -3349,7 +3393,7 @@ static void service_notify_cgroup_empty_event(Unit *u) { + * SIGCHLD for. */ + + case SERVICE_START: +- if (s->type == SERVICE_NOTIFY && ++ if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) && + main_pid_good(s) == 0 && + control_pid_good(s) == 0) { + /* No chance of getting a ready notification anymore */ +@@ -3553,17 +3597,19 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + } else { + s->main_command = NULL; + +- /* Services with ExitType=cgroup do not act on main PID exiting, +- * unless the cgroup is already empty */ ++ /* Services with ExitType=cgroup do not act on main PID exiting, unless the cgroup is ++ * already empty */ + if (s->exit_type == SERVICE_EXIT_MAIN || cgroup_good(s) <= 0) { + /* The service exited, so the service is officially gone. */ + switch (s->state) { + + case SERVICE_START_POST: + case SERVICE_RELOAD: +- /* If neither main nor control processes are running then +- * the current state can never exit cleanly, hence immediately +- * terminate the service. */ ++ case SERVICE_RELOAD_SIGNAL: ++ case SERVICE_RELOAD_NOTIFY: ++ /* If neither main nor control processes are running then the current ++ * state can never exit cleanly, hence immediately terminate the ++ * service. */ + if (control_pid_good(s) <= 0) + service_enter_stop(s, f); + +@@ -3582,7 +3628,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + else + service_enter_signal(s, SERVICE_STOP_SIGTERM, f); + break; +- } else if (s->type == SERVICE_NOTIFY) { ++ } else if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD)) { + /* Only enter running through a notification, so that the + * SERVICE_START state signifies that no ready notification + * has been received */ +@@ -3675,15 +3721,13 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + s->control_command->command_next && + f == SERVICE_SUCCESS) { + +- /* There is another command to * +- * execute, so let's do that. */ ++ /* There is another command to * execute, so let's do that. */ + + log_unit_debug(u, "Running next control command for state %s.", service_state_to_string(s->state)); + service_run_next_control(s); + + } else { +- /* No further commands for this step, so let's +- * figure out what to do next */ ++ /* No further commands for this step, so let's figure out what to do next */ + + s->control_command = NULL; + s->control_command_id = _SERVICE_EXEC_COMMAND_INVALID; +@@ -3761,12 +3805,22 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + break; + + case SERVICE_RELOAD: ++ case SERVICE_RELOAD_SIGNAL: ++ case SERVICE_RELOAD_NOTIFY: + if (f == SERVICE_SUCCESS) + if (service_load_pid_file(s, true) < 0) + service_search_main_pid(s); + + s->reload_result = f; +- service_enter_running(s, SERVICE_SUCCESS); ++ ++ /* If the last notification we received from the service process indiciates ++ * we are still reloading, then don't leave reloading state just yet, just ++ * transition into SERVICE_RELOAD_NOTIFY, to wait for the READY=1 coming, ++ * too. */ ++ if (s->notify_state == NOTIFY_RELOADING) ++ service_set_state(s, SERVICE_RELOAD_NOTIFY); ++ else ++ service_enter_running(s, SERVICE_SUCCESS); + break; + + case SERVICE_STOP: +@@ -3869,6 +3923,8 @@ static int service_dispatch_timer(sd_event_source *source, usec_t usec, void *us + break; + + case SERVICE_RELOAD: ++ case SERVICE_RELOAD_SIGNAL: ++ case SERVICE_RELOAD_NOTIFY: + log_unit_warning(UNIT(s), "Reload operation timed out. Killing reload process."); + service_kill_control_process(s); + s->reload_result = SERVICE_FAILURE_TIMEOUT; +@@ -4094,6 +4150,7 @@ static void service_notify_message( + + Service *s = SERVICE(u); + bool notify_dbus = false; ++ usec_t monotonic_usec = USEC_INFINITY; + const char *e; + int r; + +@@ -4112,7 +4169,7 @@ static void service_notify_message( + + /* Interpret MAINPID= */ + e = strv_find_startswith(tags, "MAINPID="); +- if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD)) { ++ if (e && IN_SET(s->state, SERVICE_START, SERVICE_START_POST, SERVICE_RUNNING, SERVICE_RELOAD, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY)) { + pid_t new_main_pid; + + if (parse_pid(e, &new_main_pid) < 0) +@@ -4141,43 +4198,73 @@ static void service_notify_message( + } + } + +- /* Interpret READY=/STOPPING=/RELOADING=. Last one wins. */ +- STRV_FOREACH_BACKWARDS(i, tags) { ++ /* Parse MONOTONIC_USEC= */ ++ e = strv_find_startswith(tags, "MONOTONIC_USEC="); ++ if (e) { ++ r = safe_atou64(e, &monotonic_usec); ++ if (r < 0) ++ log_unit_warning_errno(u, r, "Failed to parse MONOTONIC_USEC= field in notification message, ignoring: %s", e); ++ } + +- if (streq(*i, "READY=1")) { +- s->notify_state = NOTIFY_READY; ++ /* Interpret READY=/STOPPING=/RELOADING=. STOPPING= wins over the others, and READY= over RELOADING= */ ++ if (strv_contains(tags, "STOPPING=1")) { ++ s->notify_state = NOTIFY_STOPPING; + +- /* Type=notify services inform us about completed +- * initialization with READY=1 */ +- if (s->type == SERVICE_NOTIFY && s->state == SERVICE_START) +- service_enter_start_post(s); ++ if (IN_SET(s->state, SERVICE_RUNNING, SERVICE_RELOAD_SIGNAL, SERVICE_RELOAD_NOTIFY)) ++ service_enter_stop_by_notify(s); + +- /* Sending READY=1 while we are reloading informs us +- * that the reloading is complete */ +- if (s->state == SERVICE_RELOAD && s->control_pid == 0) +- service_enter_running(s, SERVICE_SUCCESS); ++ notify_dbus = true; + +- notify_dbus = true; +- break; ++ } else if (strv_contains(tags, "READY=1")) { + +- } else if (streq(*i, "RELOADING=1")) { +- s->notify_state = NOTIFY_RELOADING; ++ s->notify_state = NOTIFY_READY; + +- if (s->state == SERVICE_RUNNING) +- service_enter_reload_by_notify(s); ++ /* Type=notify services inform us about completed initialization with READY=1 */ ++ if (IN_SET(s->type, SERVICE_NOTIFY, SERVICE_NOTIFY_RELOAD) && ++ s->state == SERVICE_START) ++ service_enter_start_post(s); + +- notify_dbus = true; +- break; ++ /* Sending READY=1 while we are reloading informs us that the reloading is complete. */ ++ if (s->state == SERVICE_RELOAD_NOTIFY) ++ service_enter_running(s, SERVICE_SUCCESS); + +- } else if (streq(*i, "STOPPING=1")) { +- s->notify_state = NOTIFY_STOPPING; ++ /* Combined RELOADING=1 and READY=1? Then this is indication that the service started and ++ * immediately finished reloading. */ ++ if (s->state == SERVICE_RELOAD_SIGNAL && ++ strv_contains(tags, "RELOADING=1") && ++ monotonic_usec != USEC_INFINITY && ++ monotonic_usec >= s->reload_begin_usec) { ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + +- if (s->state == SERVICE_RUNNING) +- service_enter_stop_by_notify(s); ++ /* Propagate a reload explicitly */ ++ r = manager_propagate_reload(UNIT(s)->manager, UNIT(s), JOB_FAIL, &error); ++ if (r < 0) ++ log_unit_warning(UNIT(s), "Failed to schedule propagation of reload, ignoring: %s", bus_error_message(&error, r)); + +- notify_dbus = true; +- break; ++ service_enter_running(s, SERVICE_SUCCESS); + } ++ ++ notify_dbus = true; ++ ++ } else if (strv_contains(tags, "RELOADING=1")) { ++ ++ s->notify_state = NOTIFY_RELOADING; ++ ++ /* Sending RELOADING=1 after we send SIGHUP to request a reload will transition ++ * things to "reload-notify" state, where we'll wait for READY=1 to let us know the ++ * reload is done. Note that we insist on a timestamp being sent along here, so that ++ * we know for sure this is a reload cycle initiated *after* we sent the signal */ ++ if (s->state == SERVICE_RELOAD_SIGNAL && ++ monotonic_usec != USEC_INFINITY && ++ monotonic_usec >= s->reload_begin_usec) ++ /* Note, we don't call service_enter_reload_by_notify() here, because we ++ * don't need reload propagation nor do we want to restart the time-out. */ ++ service_set_state(s, SERVICE_RELOAD_NOTIFY); ++ ++ if (s->state == SERVICE_RUNNING) ++ service_enter_reload_by_notify(s); ++ ++ notify_dbus = true; + } + + /* Interpret STATUS= */ +@@ -4307,7 +4394,9 @@ static bool pick_up_pid_from_bus_name(Service *s) { + SERVICE_START, + SERVICE_START_POST, + SERVICE_RUNNING, +- SERVICE_RELOAD); ++ SERVICE_RELOAD, ++ SERVICE_RELOAD_SIGNAL, ++ SERVICE_RELOAD_NOTIFY); + } + + static int bus_name_pid_lookup_callback(sd_bus_message *reply, void *userdata, sd_bus_error *ret_error) { +@@ -4514,6 +4603,8 @@ static bool service_needs_console(Unit *u) { + SERVICE_START_POST, + SERVICE_RUNNING, + SERVICE_RELOAD, ++ SERVICE_RELOAD_SIGNAL, ++ SERVICE_RELOAD_NOTIFY, + SERVICE_STOP, + SERVICE_STOP_WATCHDOG, + SERVICE_STOP_SIGTERM, +@@ -4636,13 +4727,14 @@ static const char* const service_restart_table[_SERVICE_RESTART_MAX] = { + DEFINE_STRING_TABLE_LOOKUP(service_restart, ServiceRestart); + + static const char* const service_type_table[_SERVICE_TYPE_MAX] = { +- [SERVICE_SIMPLE] = "simple", +- [SERVICE_FORKING] = "forking", +- [SERVICE_ONESHOT] = "oneshot", +- [SERVICE_DBUS] = "dbus", +- [SERVICE_NOTIFY] = "notify", +- [SERVICE_IDLE] = "idle", +- [SERVICE_EXEC] = "exec", ++ [SERVICE_SIMPLE] = "simple", ++ [SERVICE_FORKING] = "forking", ++ [SERVICE_ONESHOT] = "oneshot", ++ [SERVICE_DBUS] = "dbus", ++ [SERVICE_NOTIFY] = "notify", ++ [SERVICE_NOTIFY_RELOAD] = "notify-reload", ++ [SERVICE_IDLE] = "idle", ++ [SERVICE_EXEC] = "exec", + }; + + DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType); +diff --git a/src/core/service.h b/src/core/service.h +index 91e02e6d7e..194067f0e1 100644 +--- a/src/core/service.h ++++ b/src/core/service.h +@@ -24,13 +24,14 @@ typedef enum ServiceRestart { + } ServiceRestart; + + typedef enum ServiceType { +- SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */ +- SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */ +- SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */ +- SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */ +- SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */ +- SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */ +- SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */ ++ SERVICE_SIMPLE, /* we fork and go on right-away (i.e. modern socket activated daemons) */ ++ SERVICE_FORKING, /* forks by itself (i.e. traditional daemons) */ ++ SERVICE_ONESHOT, /* we fork and wait until the program finishes (i.e. programs like fsck which run and need to finish before we continue) */ ++ SERVICE_DBUS, /* we fork and wait until a specific D-Bus name appears on the bus */ ++ SERVICE_NOTIFY, /* we fork and wait until a daemon sends us a ready message with sd_notify() */ ++ SERVICE_NOTIFY_RELOAD, /* just like SERVICE_NOTIFY, but also implements a reload protocol via SIGHUP */ ++ SERVICE_IDLE, /* much like simple, but delay exec() until all jobs are dispatched. */ ++ SERVICE_EXEC, /* we fork and wait until we execute exec() (this means our own setup is waited for) */ + _SERVICE_TYPE_MAX, + _SERVICE_TYPE_INVALID = -EINVAL, + } ServiceType; +@@ -215,6 +216,9 @@ struct Service { + bool flush_n_restarts; + + OOMPolicy oom_policy; ++ ++ int reload_signal; ++ usec_t reload_begin_usec; + }; + + static inline usec_t service_timeout_abort_usec(Service *s) { +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 922011eccd..a9844e1cc3 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -2065,7 +2065,8 @@ static int bus_append_kill_property(sd_bus_message *m, const char *field, const + if (STR_IN_SET(field, "KillSignal", + "RestartKillSignal", + "FinalKillSignal", +- "WatchdogSignal")) ++ "WatchdogSignal", ++ "ReloadSignal")) + return bus_append_signal_from_string(m, field, eq); + + return 0; diff --git a/0442-man-document-Type-notify-reload.patch b/0442-man-document-Type-notify-reload.patch new file mode 100644 index 0000000..be65f70 --- /dev/null +++ b/0442-man-document-Type-notify-reload.patch @@ -0,0 +1,420 @@ +From e8de964c146f67c91acdaff076420282c2d1b217 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 18:13:27 +0100 +Subject: [PATCH] man: document Type=notify-reload + +(cherry picked from commit 81e19b6f6585d656e972efad73781e184ca0e7a0) + +Related: RHEL-6090 +--- + man/sd_notify.xml | 36 ++++-- + man/systemd.service.xml | 248 ++++++++++++++++++++++------------------ + 2 files changed, 162 insertions(+), 122 deletions(-) + +diff --git a/man/sd_notify.xml b/man/sd_notify.xml +index de402950bb..d2dba00004 100644 +--- a/man/sd_notify.xml ++++ b/man/sd_notify.xml +@@ -102,23 +102,35 @@ + + READY=1 + +- Tells the service manager that service startup is finished, or the service finished loading its +- configuration. This is only used by systemd if the service definition file has Type=notify +- set. Since there is little value in signaling non-readiness, the only value services should send is +- READY=1 (i.e. READY=0 is not defined). ++ Tells the service manager that service startup is finished, or the service finished ++ re-loading its configuration. This is only used by systemd if the service definition file has ++ Type=notify or Type=notify-reload set. Since there is little ++ value in signaling non-readiness, the only value services should send is READY=1 ++ (i.e. READY=0 is not defined). + + + + RELOADING=1 + +- Tells the service manager that the service is +- reloading its configuration. This is useful to allow the +- service manager to track the service's internal state, and +- present it to the user. Note that a service that sends this +- notification must also send a READY=1 +- notification when it completed reloading its +- configuration. Reloads are propagated in the same way as they +- are when initiated by the user. ++ Tells the service manager that the service is beginning to reload its ++ configuration. This is useful to allow the service manager to track the service's internal state, and ++ present it to the user. Note that a service that sends this notification must also send a ++ READY=1 notification when it completed reloading its configuration. Reloads the ++ service manager is notified about with this mechanisms are propagated in the same way as they are ++ when originally initiated through the service manager. This message is particularly relevant for ++ Type=notify-reload services, to inform the service manager that the request to ++ reload the service has been received and is now being processed. ++ ++ ++ ++ MONOTONIC_USEC=… ++ ++ A field carrying the monotonic timestamp (as per ++ CLOCK_MONOTONIC) formatted in decimal in µs, when the notification message was ++ generated by the client. This is typically used in combination with RELOADING=1, ++ to allow the service manager to properly synchronize reload cycles. See ++ systemd.service5 ++ for details, specifically Type=notify-reload. + + + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index 1c9e59f722..ae54332440 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -157,7 +157,7 @@ + + Configures the process start-up type for this service unit. One of , + , , , , +- or : ++ , or : + + + If set to (the default if ExecStart= is +@@ -216,14 +216,30 @@ + logic thus should be prepared to receive a SIGTERM (or whichever signal is + configured in KillSignal=) as result. + +- Behavior of is similar to ; however, it is +- expected that the service sends a notification message via +- sd_notify3 or an +- equivalent call when it has finished starting up. systemd will proceed with starting follow-up units after +- this notification message has been sent. If this option is used, NotifyAccess= (see +- below) should be set to open access to the notification socket provided by systemd. If +- NotifyAccess= is missing or set to , it will be forcibly set to +- . ++ Behavior of is similar to ; however, ++ it is expected that the service sends a READY=1 notification message via ++ sd_notify3 or ++ an equivalent call when it has finished starting up. systemd will proceed with starting follow-up ++ units after this notification message has been sent. If this option is used, ++ NotifyAccess= (see below) should be set to open access to the notification ++ socket provided by systemd. If NotifyAccess= is missing or set to ++ , it will be forcibly set to . ++ ++ Behavior of is identical to ++ . However, it extends the logic in one way: the ++ SIGHUP UNIX process signal is sent to the service's main process when the ++ service is asked to reload. (The signal to send can be tweaked via ++ ReloadSignal=, see below.). When ++ initiating the reload process the service is then expected to reply with a notification message ++ via sd_notify3 ++ that contains the RELOADING=1 field in combination with ++ MONOTONIC_USEC= set to the current monotonic time ++ (i.e. CLOCK_MONOTONIC in ++ clock_gettime2) ++ in µs, formatted as decimal string. Once reloading is complete another notification message must ++ be sent, containing READY=1. Using this service type and implementing this ++ reload protocol is an efficient alternative to providing an ExecReload= ++ command for reloading of the service's configuration. + + Behavior of is very similar to ; however, + actual execution of the service program is delayed until all active jobs are dispatched. This may be used +@@ -233,25 +249,27 @@ + anyway. + + +- It is generally recommended to use Type= for long-running +- services whenever possible, as it is the simplest and fastest option. However, as this service type won't +- propagate service start-up failures and doesn't allow ordering of other units against completion of +- initialization of the service (which for example is useful if clients need to connect to the service through +- some form of IPC, and the IPC channel is only established by the service itself — in contrast to doing this +- ahead of time through socket or bus activation or similar), it might not be sufficient for many cases. If so, +- or (the latter only in case the service provides a D-Bus +- interface) are the preferred options as they allow service program code to precisely schedule when to +- consider the service started up successfully and when to proceed with follow-up units. The +- service type requires explicit support in the service codebase (as +- sd_notify() or an equivalent API needs to be invoked by the service at the appropriate +- time) — if it's not supported, then is an alternative: it supports the traditional +- UNIX service start-up protocol. Finally, might be an option for cases where it is +- enough to ensure the service binary is invoked, and where the service binary itself executes no or little +- initialization on its own (and its initialization is unlikely to fail). Note that using any type other than +- possibly delays the boot process, as the service manager needs to wait for service +- initialization to complete. It is hence recommended not to needlessly use any types other than +- . (Also note it is generally not recommended to use or +- for long-running services.) ++ It is generally recommended to use Type= for ++ long-running services whenever possible, as it is the simplest and fastest option. However, as this ++ service type won't propagate service start-up failures and doesn't allow ordering of other units ++ against completion of initialization of the service (which for example is useful if clients need to ++ connect to the service through some form of IPC, and the IPC channel is only established by the ++ service itself — in contrast to doing this ahead of time through socket or bus activation or ++ similar), it might not be sufficient for many cases. If so, , ++ or (the latter only in case the service ++ provides a D-Bus interface) are the preferred options as they allow service program code to ++ precisely schedule when to consider the service started up successfully and when to proceed with ++ follow-up units. The / service types require ++ explicit support in the service codebase (as sd_notify() or an equivalent API ++ needs to be invoked by the service at the appropriate time) — if it's not supported, then ++ is an alternative: it supports the traditional UNIX service start-up ++ protocol. Finally, might be an option for cases where it is enough to ensure ++ the service binary is invoked, and where the service binary itself executes no or little ++ initialization on its own (and its initialization is unlikely to fail). Note that using any type ++ other than possibly delays the boot process, as the service manager needs ++ to wait for service initialization to complete. It is hence recommended not to needlessly use any ++ types other than . (Also note it is generally not recommended to use ++ or for long-running services.) + + + +@@ -319,9 +337,10 @@ + the file may not be a symlink to a file owned by a different user (neither directly nor indirectly), and the + PID file must refer to a process already belonging to the service. + +- Note that PID files should be avoided in modern projects. Use or +- where possible, which does not require use of PID files to determine the +- main process of a service and avoids needless forking. ++ Note that PID files should be avoided in modern projects. Use , ++ or where possible, which does not ++ require use of PID files to determine the main process of a service and avoids needless ++ forking. + + + +@@ -443,12 +462,13 @@ + with a - exit successfully. + + ExecStartPost= commands are only run after the commands specified in +- ExecStart= have been invoked successfully, as determined by Type= +- (i.e. the process has been started for Type=simple or Type=idle, the last +- ExecStart= process exited successfully for Type=oneshot, the initial +- process exited successfully for Type=forking, READY=1 is sent for +- Type=notify, or the BusName= has been taken for +- Type=dbus). ++ ExecStart= have been invoked successfully, as determined by ++ Type= (i.e. the process has been started for Type=simple or ++ Type=idle, the last ExecStart= process exited successfully for ++ Type=oneshot, the initial process exited successfully for ++ Type=forking, READY=1 is sent for ++ Type=notify/Type=notify-reload, or the ++ BusName= has been taken for Type=dbus). + + Note that ExecStartPre= may not be + used to start long-running processes. All processes forked +@@ -487,30 +507,26 @@ + + + ExecReload= +- Commands to execute to trigger a configuration +- reload in the service. This argument takes multiple command +- lines, following the same scheme as described for +- ExecStart= above. Use of this setting is +- optional. Specifier and environment variable substitution is +- supported here following the same scheme as for ++ ++ Commands to execute to trigger a configuration reload in the service. This argument ++ takes multiple command lines, following the same scheme as described for ++ ExecStart= above. Use of this setting is optional. Specifier and environment ++ variable substitution is supported here following the same scheme as for + ExecStart=. + +- One additional, special environment variable is set: if +- known, $MAINPID is set to the main process +- of the daemon, and may be used for command lines like the +- following: ++ One additional, special environment variable is set: if known, $MAINPID is ++ set to the main process of the daemon, and may be used for command lines like the following: + + ExecReload=kill -HUP $MAINPID + +- Note however that reloading a daemon by sending a signal +- (as with the example line above) is usually not a good choice, +- because this is an asynchronous operation and hence not +- suitable to order reloads of multiple services against each +- other. It is strongly recommended to set +- ExecReload= to a command that not only +- triggers a configuration reload of the daemon, but also +- synchronously waits for it to complete. For example, +- dbus-broker1 ++ Note however that reloading a daemon by enqueing a signal (as with the example line above) is ++ usually not a good choice, because this is an asynchronous operation and hence not suitable when ++ ordering reloads of multiple services against each other. It is thus strongly recommended to either ++ use Type= in place of ++ ExecReload=, or to set ExecReload= to a command that not only ++ triggers a configuration reload of the daemon, but also synchronously waits for it to complete. For ++ example, dbus-broker1 + uses the following: + + ExecReload=busctl call org.freedesktop.DBus \ +@@ -605,12 +621,13 @@ + systemd-system.conf5). + + +- If a service of Type=notify sends EXTEND_TIMEOUT_USEC=…, this may cause +- the start time to be extended beyond TimeoutStartSec=. The first receipt of this message +- must occur before TimeoutStartSec= is exceeded, and once the start time has extended beyond +- TimeoutStartSec=, the service manager will allow the service to continue to start, provided +- the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified until the service +- startup status is finished by READY=1. (see ++ If a service of Type=notify/Type=notify-reload sends ++ EXTEND_TIMEOUT_USEC=…, this may cause the start time to be extended beyond ++ TimeoutStartSec=. The first receipt of this message must occur before ++ TimeoutStartSec= is exceeded, and once the start time has extended beyond ++ TimeoutStartSec=, the service manager will allow the service to continue to start, ++ provided the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified ++ until the service startup status is finished by READY=1. (see + sd_notify3). + + +@@ -633,12 +650,14 @@ + systemd-system.conf5). + + +- If a service of Type=notify sends EXTEND_TIMEOUT_USEC=…, this may cause +- the stop time to be extended beyond TimeoutStopSec=. The first receipt of this message +- must occur before TimeoutStopSec= is exceeded, and once the stop time has extended beyond +- TimeoutStopSec=, the service manager will allow the service to continue to stop, provided +- the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified, or terminates itself +- (see sd_notify3). ++ If a service of Type=notify/Type=notify-reload sends ++ EXTEND_TIMEOUT_USEC=…, this may cause the stop time to be extended beyond ++ TimeoutStopSec=. The first receipt of this message must occur before ++ TimeoutStopSec= is exceeded, and once the stop time has extended beyond ++ TimeoutStopSec=, the service manager will allow the service to continue to stop, ++ provided the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified, ++ or terminates itself (see ++ sd_notify3). + + + +@@ -661,13 +680,15 @@ + systemd-system.conf5). + + +- If a service of Type=notify handles SIGABRT itself (instead of relying +- on the kernel to write a core dump) it can send EXTEND_TIMEOUT_USEC=… to +- extended the abort time beyond TimeoutAbortSec=. The first receipt of this message +- must occur before TimeoutAbortSec= is exceeded, and once the abort time has extended beyond +- TimeoutAbortSec=, the service manager will allow the service to continue to abort, provided +- the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified, or terminates itself +- (see sd_notify3). ++ If a service of Type=notify/Type=notify-reload handles ++ SIGABRT itself (instead of relying on the kernel to write a core dump) it can ++ send EXTEND_TIMEOUT_USEC=… to extended the abort time beyond ++ TimeoutAbortSec=. The first receipt of this message must occur before ++ TimeoutAbortSec= is exceeded, and once the abort time has extended beyond ++ TimeoutAbortSec=, the service manager will allow the service to continue to abort, ++ provided the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified, ++ or terminates itself (see ++ sd_notify3). + + + +@@ -710,12 +731,13 @@ + activation completed. Pass infinity (the default) to configure no runtime + limit. + +- If a service of Type=notify sends EXTEND_TIMEOUT_USEC=…, this may cause +- the runtime to be extended beyond RuntimeMaxSec=. The first receipt of this message +- must occur before RuntimeMaxSec= is exceeded, and once the runtime has extended beyond +- RuntimeMaxSec=, the service manager will allow the service to continue to run, provided +- the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified until the service +- shutdown is achieved by STOPPING=1 (or termination). (see ++ If a service of Type=notify/Type=notify-reload sends ++ EXTEND_TIMEOUT_USEC=…, this may cause the runtime to be extended beyond ++ RuntimeMaxSec=. The first receipt of this message must occur before ++ RuntimeMaxSec= is exceeded, and once the runtime has extended beyond ++ RuntimeMaxSec=, the service manager will allow the service to continue to run, ++ provided the service repeats EXTEND_TIMEOUT_USEC=… within the interval specified ++ until the service shutdown is achieved by STOPPING=1 (or termination). (see + sd_notify3). + + +@@ -1023,16 +1045,19 @@ + + NotifyAccess= + Controls access to the service status notification socket, as accessible via the +- sd_notify3 call. Takes one +- of (the default), , or +- . If , no daemon status updates are accepted from the service +- processes, all status update messages are ignored. If , only service updates sent from the +- main process of the service are accepted. If , only service updates sent from any of the +- main or control processes originating from one of the Exec*= commands are accepted. If +- , all services updates from all members of the service's control group are accepted. This +- option should be set to open access to the notification socket when using Type=notify or +- WatchdogSec= (see above). If those options are used but NotifyAccess= is +- not configured, it will be implicitly set to . ++ sd_notify3 ++ call. Takes one of (the default), , ++ or . If , no daemon status updates are accepted from the ++ service processes, all status update messages are ignored. If , only service ++ updates sent from the main process of the service are accepted. If , only ++ service updates sent from any of the main or control processes originating from one of the ++ Exec*= commands are accepted. If , all services updates from ++ all members of the service's control group are accepted. This option should be set to open access to ++ the notification socket when using ++ Type=notify/Type=notify-reload or ++ WatchdogSec= (see above). If those options are used but ++ NotifyAccess= is not configured, it will be implicitly set to ++ . + + Note that sd_notify() notifications may be attributed to units correctly only if + either the sending process is still around at the time PID 1 processes the message, or if the sending process +@@ -1156,6 +1181,15 @@ + kills, this setting determines the state of the unit after systemd-oomd kills a + cgroup associated with it. + ++ ++ ++ ReloadSignal= ++ Configures the UNIX process signal to send to the service's main process when asked ++ to reload the service's configuration. Defaults to SIGHUP. This option has no ++ effect unless Type= is used, see ++ above. ++ ++ + + + Check +@@ -1319,16 +1353,13 @@ WantedBy=multi-user.target + systemd.kill5 + for details. + +- Note that this unit type does not include any type of +- notification when a service has completed initialization. For +- this, you should use other unit types, such as +- Type= if the service +- understands systemd's notification protocol, +- Type= if the service +- can background itself or +- Type= if the unit +- acquires a DBus name once initialization is complete. See +- below. ++ Note that this unit type does not include any type of notification when a service has completed ++ initialization. For this, you should use other unit types, such as ++ Type=/Type= ++ if the service understands systemd's notification protocol, ++ Type= if the service can background itself or ++ Type= if the unit acquires a DBus name once initialization is ++ complete. See below. + + + +@@ -1505,15 +1536,12 @@ SystemdService=simple-dbus-service.service + + Services that notify systemd about their initialization + +- Type= services +- are really easy to write, but have the major disadvantage of +- systemd not being able to tell when initialization of the given +- service is complete. For this reason, systemd supports a simple +- notification protocol that allows daemons to make systemd aware +- that they are done initializing. Use +- Type= for this. A +- typical service file for such a daemon would look like +- this: ++ Type= services are really easy to write, but have the ++ major disadvantage of systemd not being able to tell when initialization of the given service is ++ complete. For this reason, systemd supports a simple notification protocol that allows daemons to make ++ systemd aware that they are done initializing. Use Type= or ++ Type= for this. A typical service file for such a ++ daemon would look like this: + + [Unit] + Description=Simple notifying service diff --git a/0443-pid1-make-sure-we-send-our-calling-service-manager-R.patch b/0443-pid1-make-sure-we-send-our-calling-service-manager-R.patch new file mode 100644 index 0000000..61044dd --- /dev/null +++ b/0443-pid1-make-sure-we-send-our-calling-service-manager-R.patch @@ -0,0 +1,105 @@ +From 567b6dcd4ff8e4a9c9b0b1629fa8c015d5e6a724 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 15:01:56 +0100 +Subject: [PATCH] pid1: make sure we send our calling service manager + RELOADING=1 when reloading + +And send READY=1 again when we are done with it. + +We do this not only for "daemon-reload" but also for "daemon-reexec" and +"switch-root", since from the perspective of an encapsulating service +manager these three operations are not that different. + +(cherry picked from commit dd0ab174c36492cdcb92cf46844fb0905b1d4a7e) + +Related: RHEL-6090 +--- + src/core/main.c | 10 ++++++++++ + src/core/manager.c | 12 ++++++++++++ + src/core/manager.h | 1 + + units/user@.service.in | 2 +- + 4 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 0e2e5448bb..126a4bce8c 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -1925,6 +1925,8 @@ static int invoke_main_loop( + LogTarget saved_log_target; + int saved_log_level; + ++ manager_send_reloading(m); ++ + log_info("Reloading."); + + /* First, save any overridden log level/target, then parse the configuration file, +@@ -1955,6 +1957,10 @@ static int invoke_main_loop( + } + + case MANAGER_REEXECUTE: ++ ++ manager_send_reloading(m); /* From the perspective of the manager calling us this is ++ * pretty much the same as a reload */ ++ + r = prepare_reexecute(m, &arg_serialization, ret_fds, false); + if (r < 0) { + *ret_error_message = "Failed to prepare for reexecution"; +@@ -1970,6 +1976,10 @@ static int invoke_main_loop( + return objective; + + case MANAGER_SWITCH_ROOT: ++ ++ manager_send_reloading(m); /* From the perspective of the manager calling us this is ++ * pretty much the same as a reload */ ++ + manager_set_switching_root(m, true); + + if (!m->switch_root_init) { +diff --git a/src/core/manager.c b/src/core/manager.c +index 6371810ce3..b34103d7d3 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -3641,6 +3641,18 @@ void manager_check_finished(Manager *m) { + manager_invalidate_startup_units(m); + } + ++void manager_send_reloading(Manager *m) { ++ assert(m); ++ ++ /* Let whoever invoked us know that we are now reloading */ ++ (void) sd_notifyf(/* unset= */ false, ++ "RELOADING=1\n" ++ "MONOTONIC_USEC=" USEC_FMT "\n", now(CLOCK_MONOTONIC)); ++ ++ /* And ensure that we'll send READY=1 again as soon as we are ready again */ ++ m->ready_sent = false; ++} ++ + static bool generator_path_any(const char* const* paths) { + bool found = false; + +diff --git a/src/core/manager.h b/src/core/manager.h +index 75c16d6e26..87e63c3b68 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -535,6 +535,7 @@ void manager_send_unit_plymouth(Manager *m, Unit *u); + bool manager_unit_inactive_or_pending(Manager *m, const char *name); + + void manager_check_finished(Manager *m); ++void manager_send_reloading(Manager *m); + + void disable_printk_ratelimit(void); + void manager_recheck_dbus(Manager *m); +diff --git a/units/user@.service.in b/units/user@.service.in +index efbd5dfbc8..2c99f50905 100644 +--- a/units/user@.service.in ++++ b/units/user@.service.in +@@ -17,7 +17,7 @@ IgnoreOnIsolate=yes + [Service] + User=%i + PAMName=systemd-user +-Type=notify ++Type=notify-reload + ExecStart={{ROOTLIBEXECDIR}}/systemd --user + Slice=user-%i.slice + KillMode=mixed diff --git a/0444-networkd-implement-Type-notify-reload-protocol.patch b/0444-networkd-implement-Type-notify-reload-protocol.patch new file mode 100644 index 0000000..75ba689 --- /dev/null +++ b/0444-networkd-implement-Type-notify-reload-protocol.patch @@ -0,0 +1,166 @@ +From fef242735b987c1870bcd0460cc0c802e78a3cde Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 17:25:46 +0100 +Subject: [PATCH] networkd: implement Type=notify-reload protocol + +(cherry picked from commit 0e07cdb0e77d0322bc866b5e13abbe38e988059d) + +Related: RHEL-6090 +--- + src/network/networkd-manager-bus.c | 13 +------- + src/network/networkd-manager.c | 48 ++++++++++++++++++++++++++---- + src/network/networkd-manager.h | 2 ++ + src/network/networkd.c | 2 -- + units/systemd-networkd.service.in | 3 +- + 5 files changed, 47 insertions(+), 21 deletions(-) + +diff --git a/src/network/networkd-manager-bus.c b/src/network/networkd-manager-bus.c +index 2ab3aaadc2..67f951df69 100644 +--- a/src/network/networkd-manager-bus.c ++++ b/src/network/networkd-manager-bus.c +@@ -197,7 +197,6 @@ static int bus_method_reconfigure_link(sd_bus_message *message, void *userdata, + + static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *manager = userdata; +- Link *link; + int r; + + r = bus_verify_polkit_async(message, CAP_NET_ADMIN, +@@ -209,20 +208,10 @@ static int bus_method_reload(sd_bus_message *message, void *userdata, sd_bus_err + if (r == 0) + return 1; /* Polkit will call us back */ + +- r = netdev_load(manager, true); ++ r = manager_reload(manager); + if (r < 0) + return r; + +- r = network_reload(manager); +- if (r < 0) +- return r; +- +- HASHMAP_FOREACH(link, manager->links_by_index) { +- r = link_reconfigure(link, /* force = */ false); +- if (r < 0) +- return r; +- } +- + return sd_bus_reply_method_return(message, NULL); + } + +diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c +index cdfd29bc0e..362ee84b09 100644 +--- a/src/network/networkd-manager.c ++++ b/src/network/networkd-manager.c +@@ -483,6 +483,14 @@ static int signal_restart_callback(sd_event_source *s, const struct signalfd_sig + return sd_event_exit(sd_event_source_get_event(s), 0); + } + ++static int signal_reload_callback(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { ++ Manager *m = ASSERT_PTR(userdata); ++ ++ manager_reload(m); ++ ++ return 0; ++} ++ + static int manager_set_keep_configuration(Manager *m) { + int r; + +@@ -517,12 +525,11 @@ int manager_setup(Manager *m) { + if (r < 0) + return r; + +- assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGINT, SIGTERM, SIGUSR2, -1) >= 0); +- + (void) sd_event_set_watchdog(m->event, true); +- (void) sd_event_add_signal(m->event, NULL, SIGTERM, signal_terminate_callback, m); +- (void) sd_event_add_signal(m->event, NULL, SIGINT, signal_terminate_callback, m); +- (void) sd_event_add_signal(m->event, NULL, SIGUSR2, signal_restart_callback, m); ++ (void) sd_event_add_signal(m->event, NULL, SIGTERM | SD_EVENT_SIGNAL_PROCMASK, signal_terminate_callback, m); ++ (void) sd_event_add_signal(m->event, NULL, SIGINT | SD_EVENT_SIGNAL_PROCMASK, signal_terminate_callback, m); ++ (void) sd_event_add_signal(m->event, NULL, SIGUSR2 | SD_EVENT_SIGNAL_PROCMASK, signal_restart_callback, m); ++ (void) sd_event_add_signal(m->event, NULL, SIGHUP | SD_EVENT_SIGNAL_PROCMASK, signal_reload_callback, m); + + r = sd_event_add_post(m->event, NULL, manager_dirty_handler, m); + if (r < 0) +@@ -1078,3 +1085,34 @@ int manager_set_timezone(Manager *m, const char *tz) { + + return 0; + } ++ ++int manager_reload(Manager *m) { ++ Link *link; ++ int r; ++ ++ assert(m); ++ ++ (void) sd_notifyf(/* unset= */ false, ++ "RELOADING=1\n" ++ "STATUS=Reloading configuration...\n" ++ "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)); ++ ++ r = netdev_load(m, /* reload= */ true); ++ if (r < 0) ++ goto finish; ++ ++ r = network_reload(m); ++ if (r < 0) ++ goto finish; ++ ++ HASHMAP_FOREACH(link, m->links_by_index) { ++ r = link_reconfigure(link, /* force = */ false); ++ if (r < 0) ++ goto finish; ++ } ++ ++ r = 0; ++finish: ++ (void) sd_notify(/* unset= */ false, NOTIFY_READY); ++ return r; ++} +diff --git a/src/network/networkd-manager.h b/src/network/networkd-manager.h +index 40e6092f85..e6183af0e4 100644 +--- a/src/network/networkd-manager.h ++++ b/src/network/networkd-manager.h +@@ -115,4 +115,6 @@ int manager_enumerate(Manager *m); + int manager_set_hostname(Manager *m, const char *hostname); + int manager_set_timezone(Manager *m, const char *timezone); + ++int manager_reload(Manager *m); ++ + DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); +diff --git a/src/network/networkd.c b/src/network/networkd.c +index d61769d9f3..68760e8ff4 100644 +--- a/src/network/networkd.c ++++ b/src/network/networkd.c +@@ -81,8 +81,6 @@ static int run(int argc, char *argv[]) { + if (r < 0) + log_warning_errno(r, "Could not create runtime directory 'lldp': %m"); + +- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0); +- + r = manager_new(&m, /* test_mode = */ false); + if (r < 0) + return log_error_errno(r, "Could not create manager: %m"); +diff --git a/units/systemd-networkd.service.in b/units/systemd-networkd.service.in +index d15129e7f0..d8b935a358 100644 +--- a/units/systemd-networkd.service.in ++++ b/units/systemd-networkd.service.in +@@ -24,7 +24,6 @@ BusName=org.freedesktop.network1 + CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_BROADCAST CAP_NET_RAW + DeviceAllow=char-* rw + ExecStart=!!{{ROOTLIBEXECDIR}}/systemd-networkd +-ExecReload=networkctl reload + FileDescriptorStoreMax=512 + LockPersonality=yes + MemoryDenyWriteExecute=yes +@@ -48,7 +47,7 @@ RuntimeDirectoryPreserve=yes + SystemCallArchitectures=native + SystemCallErrorNumber=EPERM + SystemCallFilter=@system-service +-Type=notify ++Type=notify-reload + User=systemd-network + {{SERVICE_WATCHDOG}} + diff --git a/0445-udevd-implement-the-full-Type-notify-reload-protocol.patch b/0445-udevd-implement-the-full-Type-notify-reload-protocol.patch new file mode 100644 index 0000000..86daa8c --- /dev/null +++ b/0445-udevd-implement-the-full-Type-notify-reload-protocol.patch @@ -0,0 +1,127 @@ +From daa0a0268e9ed03b8e3c39f003266d0b14cae120 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 17:21:16 +0100 +Subject: [PATCH] udevd: implement the full Type=notify-reload protocol + +We are basically already there, just need to add MONOTONIC_USEC= to the +RELOADING=1 message, and make sure the message is generated in really +all cases. + +(cherry picked from commit f84331539deae28fbeb42d45ad0c8d583b3372a3) + +Related: RHEL-6090 +--- + src/udev/udevd.c | 47 +++++++++++++++++++--------------- + units/systemd-udevd.service.in | 3 +-- + 2 files changed, 28 insertions(+), 22 deletions(-) + +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index ccc3c0eece..6d82a6eff2 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -32,6 +32,7 @@ + #include "cgroup-setup.h" + #include "cgroup-util.h" + #include "cpu-set-util.h" ++#include "daemon-util.h" + #include "dev-setup.h" + #include "device-monitor-private.h" + #include "device-private.h" +@@ -331,9 +332,7 @@ static void manager_exit(Manager *manager) { + + manager->exit = true; + +- sd_notify(false, +- "STOPPING=1\n" +- "STATUS=Starting shutdown..."); ++ (void) sd_notify(/* unset= */ false, NOTIFY_STOPPING); + + /* close sources of new events and discard buffered events */ + manager->ctrl = udev_ctrl_unref(manager->ctrl); +@@ -351,7 +350,7 @@ static void manager_exit(Manager *manager) { + static void notify_ready(void) { + int r; + +- r = sd_notifyf(false, ++ r = sd_notifyf(/* unset= */ false, + "READY=1\n" + "STATUS=Processing with %u children at max", arg_children_max); + if (r < 0) +@@ -376,23 +375,33 @@ static void manager_reload(Manager *manager, bool force) { + mac_selinux_maybe_reload(); + + /* Nothing changed. It is not necessary to reload. */ +- if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload()) +- return; ++ if (!udev_rules_should_reload(manager->rules) && !udev_builtin_should_reload()) { + +- sd_notify(false, +- "RELOADING=1\n" +- "STATUS=Flushing configuration..."); ++ if (!force) ++ return; + +- manager_kill_workers(manager, false); ++ /* If we eat this up, then tell our service manager to just continue */ ++ (void) sd_notifyf(/* unset= */ false, ++ "RELOADING=1\n" ++ "STATUS=Skipping configuration reloading, nothing changed.\n" ++ "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)); ++ } else { ++ (void) sd_notifyf(/* unset= */ false, ++ "RELOADING=1\n" ++ "STATUS=Flushing configuration...\n" ++ "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)); + +- udev_builtin_exit(); +- udev_builtin_init(); ++ manager_kill_workers(manager, false); + +- r = udev_rules_load(&rules, arg_resolve_name_timing); +- if (r < 0) +- log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m"); +- else +- udev_rules_free_and_replace(manager->rules, rules); ++ udev_builtin_exit(); ++ udev_builtin_init(); ++ ++ r = udev_rules_load(&rules, arg_resolve_name_timing); ++ if (r < 0) ++ log_warning_errno(r, "Failed to read udev rules, using the previously loaded rules, ignoring: %m"); ++ else ++ udev_rules_free_and_replace(manager->rules, rules); ++ } + + notify_ready(); + } +@@ -1982,9 +1991,7 @@ static int main_loop(Manager *manager) { + if (r < 0) + log_error_errno(r, "Event loop failed: %m"); + +- sd_notify(false, +- "STOPPING=1\n" +- "STATUS=Shutting down..."); ++ (void) sd_notify(/* unset= */ false, NOTIFY_STOPPING); + return r; + } + +diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in +index e9dbe85ef4..dfc2a0e341 100644 +--- a/units/systemd-udevd.service.in ++++ b/units/systemd-udevd.service.in +@@ -18,14 +18,13 @@ ConditionPathIsReadWrite=/sys + [Service] + CapabilityBoundingSet=~CAP_SYS_TIME CAP_WAKE_ALARM + Delegate=pids +-Type=notify ++Type=notify-reload + # Note that udev will reset the value internally for its workers + OOMScoreAdjust=-1000 + Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket + Restart=always + RestartSec=0 + ExecStart={{ROOTLIBEXECDIR}}/systemd-udevd +-ExecReload=udevadm control --reload --timeout 0 + KillMode=mixed + TasksMax=infinity + PrivateMounts=yes diff --git a/0446-logind-implement-Type-notify-reload-protocol-properl.patch b/0446-logind-implement-Type-notify-reload-protocol-properl.patch new file mode 100644 index 0000000..62c47af --- /dev/null +++ b/0446-logind-implement-Type-notify-reload-protocol-properl.patch @@ -0,0 +1,52 @@ +From dd9aa5ffe940ac6d5204a04fce5faafc3fc01924 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 17:35:23 +0100 +Subject: [PATCH] logind: implement Type=notify-reload protocol properly + +So close already. Let's add the two missing notifications too. + +Fixes: #18484 +(cherry picked from commit 5d71e463f49518c7702467f6145484afa31bf8ba) + +Related: RHEL-6090 +--- + src/login/logind.c | 6 ++++++ + units/systemd-logind.service.in | 1 + + 2 files changed, 7 insertions(+) + +diff --git a/src/login/logind.c b/src/login/logind.c +index cdca5ca58c..0348b19c05 100644 +--- a/src/login/logind.c ++++ b/src/login/logind.c +@@ -1014,6 +1014,11 @@ static int manager_dispatch_reload_signal(sd_event_source *s, const struct signa + Manager *m = userdata; + int r; + ++ (void) sd_notifyf(/* unset= */ false, ++ "RELOADING=1\n" ++ "STATUS=Reloading configuration...\n" ++ "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)); ++ + manager_reset_config(m); + r = manager_parse_config_file(m); + if (r < 0) +@@ -1021,6 +1026,7 @@ static int manager_dispatch_reload_signal(sd_event_source *s, const struct signa + else + log_info("Config file reloaded."); + ++ (void) sd_notify(/* unset= */ false, NOTIFY_READY); + return 0; + } + +diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in +index 042ea75d7a..24f5ddaa17 100644 +--- a/units/systemd-logind.service.in ++++ b/units/systemd-logind.service.in +@@ -58,6 +58,7 @@ StateDirectory=systemd/linger + SystemCallArchitectures=native + SystemCallErrorNumber=EPERM + SystemCallFilter=@system-service ++Type=notify-reload + {{SERVICE_WATCHDOG}} + + # Increase the default a bit in order to allow many simultaneous logins since diff --git a/0447-notify-add-stopping-reloading-switches.patch b/0447-notify-add-stopping-reloading-switches.patch new file mode 100644 index 0000000..0486221 --- /dev/null +++ b/0447-notify-add-stopping-reloading-switches.patch @@ -0,0 +1,297 @@ +From 2b5c9fceaaa30ec9c2d031c9ca32b71c43f22f98 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 3 Jan 2023 12:55:50 +0100 +Subject: [PATCH] notify: add --stopping + --reloading switches + +These wrap RELOADING=1 and STOPPING=1 messages. The former is +particularly useful, since we want to insert the MONOTONIC_USEC= field +into the message automatically, which is easy from C but harder from +shell. + +(cherry picked from commit fd0f4da5457fbf7136f2d1888142d5fea75fd45a) + +Related: RHEL-6090 +--- + man/systemd-notify.xml | 107 ++++++++++++++++++++++++----------------- + src/notify/notify.c | 39 +++++++++++++-- + 2 files changed, 97 insertions(+), 49 deletions(-) + +diff --git a/man/systemd-notify.xml b/man/systemd-notify.xml +index 1327d23155..a275123d40 100644 +--- a/man/systemd-notify.xml ++++ b/man/systemd-notify.xml +@@ -30,34 +30,35 @@ + + Description + +- systemd-notify may be called by daemon +- scripts to notify the init system about status changes. It can be +- used to send arbitrary information, encoded in an +- environment-block-like list of strings. Most importantly, it can be +- used for start-up completion notification. +- +- This is mostly just a wrapper around +- sd_notify() and makes this functionality ++ systemd-notify may be called by service scripts to notify the invoking service ++ manager about status changes. It can be used to send arbitrary information, encoded in an ++ environment-block-like list of strings. Most importantly, it can be used for start-up completion ++ notification. ++ ++ This is mostly just a wrapper around sd_notify() and makes this functionality + available to shell scripts. For details see + sd_notify3. + + +- The command line may carry a list of environment variables +- to send as part of the status update. ++ The command line may carry a list of environment variables to send as part of the status ++ update. + + Note that systemd will refuse reception of status updates from this command unless + NotifyAccess= is set for the service unit this command is called from. + +- Note that sd_notify() notifications may be attributed to units correctly only if either +- the sending process is still around at the time PID 1 processes the message, or if the sending process is +- explicitly runtime-tracked by the service manager. The latter is the case if the service manager originally forked +- off the process, i.e. on all processes that match NotifyAccess= or +- NotifyAccess=. Conversely, if an auxiliary process of the unit sends an +- sd_notify() message and immediately exits, the service manager might not be able to properly +- attribute the message to the unit, and thus will ignore it, even if NotifyAccess= is set for it. When is used, all synchronization for reception of notifications +- is disabled, and hence the aforementioned race may occur if the invoking process is not the service manager or spawned +- by the service manager. ++ Note that sd_notify() notifications may be attributed to units correctly only ++ if either the sending process is still around at the time the service manager processes the message, or ++ if the sending process is explicitly runtime-tracked by the service manager. The latter is the case if ++ the service manager originally forked off the process, i.e. on all processes that match ++ NotifyAccess= or ++ NotifyAccess=. Conversely, if an auxiliary process of the unit ++ sends an sd_notify() message and immediately exits, the service manager might not be ++ able to properly attribute the message to the unit, and thus will ignore it, even if ++ NotifyAccess= is set for it. To address this ++ systemd-notify will wait until the notification message has been processed by the ++ service manager. When is used, this synchronization for reception of ++ notifications is disabled, and hence the aforementioned race may occur if the invoking process is not the ++ service manager or spawned by the service manager. + + Hence, systemd-notify will first attempt to invoke sd_notify() + pretending to have the PID of the invoking process. This will only succeed when invoked with sufficient privileges. +@@ -66,7 +67,6 @@ + — appears as sender of the message, which in turn is helpful if the shell process is the main process of a service, + due to the limitations of NotifyAccess=. Use the + switch to tweak this behaviour. +- + + + +@@ -78,22 +78,42 @@ + + + +- Inform the init system about service start-up +- completion. This is equivalent to systemd-notify +- READY=1. For details about the semantics of this +- option see ++ Inform the invoking service manager about service start-up or configuration reload ++ completion. This is equivalent to systemd-notify READY=1. For details about the ++ semantics of this option see ++ sd_notify3. ++ ++ ++ ++ ++ ++ Inform the invoking service manager about the beginning of a configuration reload ++ cycle. This is equivalent to systemd-notify RELOADING=1 (but implicitly also sets ++ a MONOTONIC_USEC= field as required for Type=notify-reload ++ services, see ++ systemd.service5, ++ for details). For details about the semantics of this option see ++ sd_notify3. ++ ++ ++ ++ ++ ++ Inform the invoking service manager about the beginning of the shutdown phase of the ++ service. This is equivalent to systemd-notify STOPPING=1. For details about the ++ semantics of this option see + sd_notify3. + + + + + +- Inform the service manager about the main PID of the daemon. Takes a PID as ++ Inform the service manager about the main PID of the service. Takes a PID as + argument. If the argument is specified as auto or omitted, the PID of the process + that invoked systemd-notify is used, except if that's the service manager. If the + argument is specified as self, the PID of the systemd-notify + command itself is used, and if parent is specified the calling process' PID is +- used — even if it is the service manager. This is equivalent to systemd-notify ++ used — even if it is the service manager. The latter is equivalent to systemd-notify + MAINPID=$PID. For details about the semantics of this option see + sd_notify3. + +@@ -110,27 +130,26 @@ + + + +- Send a free-form status string for the daemon +- to the init systemd. This option takes the status string as +- argument. This is equivalent to systemd-notify +- STATUS=…. For details about the semantics of this +- option see +- sd_notify3. ++ Send a free-form human readable status string for the daemon to the service ++ manager. This option takes the status string as argument. This is equivalent to ++ systemd-notify STATUS=…. For details about the semantics of this option see ++ sd_notify3. This ++ information is shown in ++ systemctl1's ++ status output, among other places. + + + + + +- Returns 0 if the system was booted up with +- systemd, non-zero otherwise. If this option is passed, no +- message is sent. This option is hence unrelated to the other +- options. For details about the semantics of this option, see ++ Returns 0 if the system was booted up with systemd, non-zero otherwise. If this ++ option is passed, no message is sent. This option is hence unrelated to the other options. For ++ details about the semantics of this option, see + sd_booted3. An + alternate way to check for this state is to call +- systemctl1 +- with the is-system-running command. It will +- return offline if the system was not booted +- with systemd. ++ systemctl1 with ++ the is-system-running command. It will return offline if the ++ system was not booted with systemd. + + + +@@ -162,9 +181,8 @@ + + Start-up Notification and Status Updates + +- A simple shell daemon that sends start-up notifications +- after having set up its communication channel. During runtime it +- sends further status updates to the init system: ++ A simple shell daemon that sends start-up notifications after having set up its communication ++ channel. During runtime it sends further status updates to the init system: + + #!/bin/sh + +@@ -192,5 +210,4 @@ done + sd_booted3 + + +- + +diff --git a/src/notify/notify.c b/src/notify/notify.c +index 7b23e7bdb0..2d4900a110 100644 +--- a/src/notify/notify.c ++++ b/src/notify/notify.c +@@ -23,6 +23,8 @@ + #include "util.h" + + static bool arg_ready = false; ++static bool arg_reloading = false; ++static bool arg_stopping = false; + static pid_t arg_pid = 0; + static const char *arg_status = NULL; + static bool arg_booted = false; +@@ -42,7 +44,10 @@ static int help(void) { + "\n%sNotify the init system about service status updates.%s\n\n" + " -h --help Show this help\n" + " --version Show package version\n" +- " --ready Inform the init system about service start-up completion\n" ++ " --ready Inform the service manager about service start-up/reload\n" ++ " completion\n" ++ " --reloading Inform the service manager about configuration reloading\n" ++ " --stopping Inform the service manager about service shutdown\n" + " --pid[=PID] Set main PID of daemon\n" + " --uid=USER Set user to send from\n" + " --status=TEXT Set status text\n" +@@ -81,6 +86,8 @@ static int parse_argv(int argc, char *argv[]) { + + enum { + ARG_READY = 0x100, ++ ARG_RELOADING, ++ ARG_STOPPING, + ARG_VERSION, + ARG_PID, + ARG_STATUS, +@@ -93,6 +100,8 @@ static int parse_argv(int argc, char *argv[]) { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "ready", no_argument, NULL, ARG_READY }, ++ { "reloading", no_argument, NULL, ARG_RELOADING }, ++ { "stopping", no_argument, NULL, ARG_STOPPING }, + { "pid", optional_argument, NULL, ARG_PID }, + { "status", required_argument, NULL, ARG_STATUS }, + { "booted", no_argument, NULL, ARG_BOOTED }, +@@ -120,6 +129,14 @@ static int parse_argv(int argc, char *argv[]) { + arg_ready = true; + break; + ++ case ARG_RELOADING: ++ arg_reloading = true; ++ break; ++ ++ case ARG_STOPPING: ++ arg_stopping = true; ++ break; ++ + case ARG_PID: + if (isempty(optarg) || streq(optarg, "auto")) { + arg_pid = getppid(); +@@ -176,6 +193,8 @@ static int parse_argv(int argc, char *argv[]) { + + if (optind >= argc && + !arg_ready && ++ !arg_stopping && ++ !arg_reloading && + !arg_status && + !arg_pid && + !arg_booted) { +@@ -187,10 +206,10 @@ static int parse_argv(int argc, char *argv[]) { + } + + static int run(int argc, char* argv[]) { +- _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL; ++ _cleanup_free_ char *status = NULL, *cpid = NULL, *n = NULL, *monotonic_usec = NULL; + _cleanup_strv_free_ char **final_env = NULL; +- char* our_env[4]; +- unsigned i = 0; ++ char* our_env[7]; ++ size_t i = 0; + pid_t source_pid; + int r; + +@@ -212,9 +231,21 @@ static int run(int argc, char* argv[]) { + return r <= 0; + } + ++ if (arg_reloading) { ++ our_env[i++] = (char*) "RELOADING=1"; ++ ++ if (asprintf(&monotonic_usec, "MONOTONIC_USEC=" USEC_FMT, now(CLOCK_MONOTONIC)) < 0) ++ return log_oom(); ++ ++ our_env[i++] = monotonic_usec; ++ } ++ + if (arg_ready) + our_env[i++] = (char*) "READY=1"; + ++ if (arg_stopping) ++ our_env[i++] = (char*) "STOPPING=1"; ++ + if (arg_status) { + status = strjoin("STATUS=", arg_status); + if (!status) diff --git a/0448-test-add-Type-notify-reload-testcase.patch b/0448-test-add-Type-notify-reload-testcase.patch new file mode 100644 index 0000000..3d21257 --- /dev/null +++ b/0448-test-add-Type-notify-reload-testcase.patch @@ -0,0 +1,74 @@ +From 3a2cb37fdbe4e761ae649716f6f8f71feffdd608 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 3 Jan 2023 12:56:53 +0100 +Subject: [PATCH] test: add Type=notify-reload testcase + +(cherry picked from commit ee52bbc68f129cfed833990906c0a0a77ee12c42) + +Related: RHEL-6090 +--- + test/units/testsuite-59.sh | 51 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/test/units/testsuite-59.sh b/test/units/testsuite-59.sh +index 83db053107..475766a851 100755 +--- a/test/units/testsuite-59.sh ++++ b/test/units/testsuite-59.sh +@@ -83,6 +83,57 @@ systemctl start testservice-abort-restart-59.service + systemctl --signal=SIGABRT kill testservice-abort-restart-59.service + wait_on_state_or_fail "testservice-abort-restart-59.service" "failed" "30" + ++# Let's now test the notify-reload logic ++ ++cat >/run/notify-reload-test.sh </testok diff --git a/0449-update-TODO.patch b/0449-update-TODO.patch new file mode 100644 index 0000000..ec98acc --- /dev/null +++ b/0449-update-TODO.patch @@ -0,0 +1,45 @@ +From 3fa498dba2e67c1c97f25b093ec6c36e55023259 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 2 Jan 2023 16:48:51 +0100 +Subject: [PATCH] update TODO + +(cherry picked from commit 6fee784964b2763bd4307181335a433078ba977c) + +Related: RHEL-6090 +--- + TODO | 15 +++------------ + 1 file changed, 3 insertions(+), 12 deletions(-) + +diff --git a/TODO b/TODO +index 66c008bff3..8c67f93f35 100644 +--- a/TODO ++++ b/TODO +@@ -700,17 +700,9 @@ Features: + and synthesize initrd from it, and measure it. Signing is not necessary, as + microcode does that on its own. Pass as first initrd to kernel. + +-* Add a new service type very similar to Type=notify, that goes one step +- further and extends the protocol to cover reloads. Specifically, SIGHUP will +- become the official way to reload, and daemon has to respond with sd_notify() +- to report when it starts reloading, and when it is complete reloading. Care +- must be taken to remove races from this model. I.e. PID 1 needs to take +- CLOCK_MONOTONIC, then send SIGHUP, then wait for at least one RELOADING=1 +- message that comes with a newer timestamp, then wait for a READY=1 message. +- while we are at it, also maybe extend the logic to require handling of some +- specific SIGRT signal for setting debug log level, that carries the level via +- the sigqueue() data parameter. With that we extended with minimal logic the +- service runtime logic quite substantially. ++* Maybe extend the service protocol to support handling of some specific SIGRT ++ signal for setting service log level, that carries the level via the ++ sigqueue() data parameter. Enable this via unit file setting. + + * firstboot: maybe just default to C.UTF-8 locale if nothing is set, so that we + don't query this unnecessarily in entirely uninitialized +@@ -1738,7 +1730,6 @@ Features: + * unit files: + - allow port=0 in .socket units + - maybe introduce ExecRestartPre= +- - add ReloadSignal= for configuring a reload signal to use + - implement Register= switch in .socket units to enable registration + in Avahi, RPC and other socket registration services. + - allow Type=simple with PIDFile= diff --git a/0450-core-check-for-SERVICE_RELOAD_NOTIFY-in-manager_dbus.patch b/0450-core-check-for-SERVICE_RELOAD_NOTIFY-in-manager_dbus.patch new file mode 100644 index 0000000..6384d8a --- /dev/null +++ b/0450-core-check-for-SERVICE_RELOAD_NOTIFY-in-manager_dbus.patch @@ -0,0 +1,40 @@ +From 036f0593b33ddc0f40a333d790a276c3cffe862e Mon Sep 17 00:00:00 2001 +From: msizanoen1 +Date: Tue, 2 May 2023 16:59:07 +0700 +Subject: [PATCH] core: check for SERVICE_RELOAD_NOTIFY in + manager_dbus_is_running + +This ensures that systemd won't erronously disconnect from the system +bus in case a bus recheck is triggered immediately after the bus service +emits `RELOADING=1`. + +This fixes an issue where systemd-logind sometimes randomly stops +receiving `UnitRemoved` after a system update. + +This also handles SERVICE_RELOAD_SIGNAL just in case somebody ever +creates a D-Bus broker implementation that uses `Type=notify-reload`. + +(cherry picked from commit 845824acddf2e7e08c94afe7cfee6e50a682c947) + +Related: RHEL-6090 +--- + src/core/manager.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index b34103d7d3..eeee395b90 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1696,7 +1696,11 @@ static bool manager_dbus_is_running(Manager *m, bool deserialized) { + u = manager_get_unit(m, SPECIAL_DBUS_SERVICE); + if (!u) + return false; +- if (!IN_SET((deserialized ? SERVICE(u)->deserialized_state : SERVICE(u)->state), SERVICE_RUNNING, SERVICE_RELOAD)) ++ if (!IN_SET((deserialized ? SERVICE(u)->deserialized_state : SERVICE(u)->state), ++ SERVICE_RUNNING, ++ SERVICE_RELOAD, ++ SERVICE_RELOAD_NOTIFY, ++ SERVICE_RELOAD_SIGNAL)) + return false; + + return true; diff --git a/systemd.spec b/systemd.spec index f83e68f..a31f474 100644 --- a/systemd.spec +++ b/systemd.spec @@ -21,7 +21,7 @@ Name: systemd Url: https://systemd.io Version: 252 -Release: 20%{?dist} +Release: 21%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -509,6 +509,25 @@ Patch0428: 0428-tree-wide-unify-how-we-pick-OS-pretty-name-to-displa.patch Patch0429: 0429-bootctl-uki-several-follow-ups-for-inspect_osrel.patch Patch0430: 0430-bootctl-Add-missing-m.patch Patch0431: 0431-bootctl-tweak-DOS-header-magic-check.patch +Patch0432: 0432-meson-fix-installation-of-ukify.patch +Patch0433: 0433-sd-id128-introduce-id128_hash_ops_free.patch +Patch0434: 0434-udevadm-trigger-allow-to-fallback-without-synthetic-.patch +Patch0435: 0435-udevadm-trigger-settle-with-synthetic-UUID-if-the-ke.patch +Patch0436: 0436-udevadm-trigger-also-check-with-the-original-syspath.patch +Patch0437: 0437-test-use-udevadm-trigger-settle-even-if-device-is-re.patch +Patch0438: 0438-sd-event-don-t-mistake-USEC_INFINITY-passed-in-for-o.patch +Patch0439: 0439-pid1-rework-service_arm_timer-to-optionally-take-a-r.patch +Patch0440: 0440-manager-add-one-more-assert.patch +Patch0441: 0441-pid1-add-new-Type-notify-reload-service-type.patch +Patch0442: 0442-man-document-Type-notify-reload.patch +Patch0443: 0443-pid1-make-sure-we-send-our-calling-service-manager-R.patch +Patch0444: 0444-networkd-implement-Type-notify-reload-protocol.patch +Patch0445: 0445-udevd-implement-the-full-Type-notify-reload-protocol.patch +Patch0446: 0446-logind-implement-Type-notify-reload-protocol-properl.patch +Patch0447: 0447-notify-add-stopping-reloading-switches.patch +Patch0448: 0448-test-add-Type-notify-reload-testcase.patch +Patch0449: 0449-update-TODO.patch +Patch0450: 0450-core-check-for-SERVICE_RELOAD_NOTIFY-in-manager_dbus.patch # Downstream-only patches (9000–9999) @@ -1332,6 +1351,27 @@ getent passwd systemd-oom &>/dev/null || useradd -r -l -g systemd-oom -d / -s /s %files standalone-sysusers -f .file-list-standalone-sysusers %changelog +* Mon Dec 11 2023 systemd maintenance team - 252-21 +- meson: fix installation of ukify (RHEL-13199) +- sd-id128: introduce id128_hash_ops_free (RHEL-5988) +- udevadm-trigger: allow to fallback without synthetic UUID only first time (RHEL-5988) +- udevadm-trigger: settle with synthetic UUID if the kernel support it (RHEL-5988) +- udevadm-trigger: also check with the original syspath if device is renamed (RHEL-5988) +- test: use 'udevadm trigger --settle' even if device is renamed (RHEL-5988) +- sd-event: don't mistake USEC_INFINITY passed in for overflow (RHEL-6090) +- pid1: rework service_arm_timer() to optionally take a relative time value (RHEL-6090) +- manager: add one more assert() (RHEL-6090) +- pid1: add new Type=notify-reload service type (RHEL-6090) +- man: document Type=notify-reload (RHEL-6090) +- pid1: make sure we send our calling service manager RELOADING=1 when reloading (RHEL-6090) +- networkd: implement Type=notify-reload protocol (RHEL-6090) +- udevd: implement the full Type=notify-reload protocol (RHEL-6090) +- logind: implement Type=notify-reload protocol properly (RHEL-6090) +- notify: add --stopping + --reloading switches (RHEL-6090) +- test: add Type=notify-reload testcase (RHEL-6090) +- update TODO (RHEL-6090) +- core: check for SERVICE_RELOAD_NOTIFY in manager_dbus_is_running (RHEL-6090) + * Fri Dec 08 2023 systemd maintenance team - 252-20 - udev/net: allow new link name as an altname before renaming happens (RHEL-5988) - sd-netlink: do not swap old name and alternative name (RHEL-5988)