systemd-252-21
Resolves: RHEL-13199,RHEL-5988,RHEL-6090
This commit is contained in:
parent
2d3ff96397
commit
484e7cdd90
30
0432-meson-fix-installation-of-ukify.patch
Normal file
30
0432-meson-fix-installation-of-ukify.patch
Normal file
@ -0,0 +1,30 @@
|
||||
From a1bd733809ff01c64a8a304a45e57277a5a98463 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
||||
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
|
37
0433-sd-id128-introduce-id128_hash_ops_free.patch
Normal file
37
0433-sd-id128-introduce-id128_hash_ops_free.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 81802cf297a05d202aae5de21673fcc7064f9b7d Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
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);
|
||||
|
104
0434-udevadm-trigger-allow-to-fallback-without-synthetic-.patch
Normal file
104
0434-udevadm-trigger-allow-to-fallback-without-synthetic-.patch
Normal file
@ -0,0 +1,104 @@
|
||||
From 597c41edd3e94f2c16209359fbd8de7ed44225d7 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
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();
|
196
0435-udevadm-trigger-settle-with-synthetic-UUID-if-the-ke.patch
Normal file
196
0435-udevadm-trigger-settle-with-synthetic-UUID-if-the-ke.patch
Normal file
@ -0,0 +1,196 @@
|
||||
From 73dbfdaab1d633e3a1ae96cc15c551eaa2fd4243 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
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");
|
@ -0,0 +1,56 @@
|
||||
From 4007f494b2e4c45f2d59948af3f4053258d3f127 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
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;
|
@ -0,0 +1,37 @@
|
||||
From ff755f035485eab0317d1320caa2748d5d4a2d78 Mon Sep 17 00:00:00 2001
|
||||
From: Yu Watanabe <watanabe.yu+github@gmail.com>
|
||||
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'
|
@ -0,0 +1,33 @@
|
||||
From e92c85b68932845c908cb3f38b2130c57065e263 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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;
|
118
0439-pid1-rework-service_arm_timer-to-optionally-take-a-r.patch
Normal file
118
0439-pid1-rework-service_arm_timer-to-optionally-take-a-r.patch
Normal file
@ -0,0 +1,118 @@
|
||||
From 917b03f2b5ccdd668a49da7df72baaddd338c071 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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;
|
||||
|
25
0440-manager-add-one-more-assert.patch
Normal file
25
0440-manager-add-one-more-assert.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From efe1737efae0950b7ded32d9c5e1a9cfaea7296b Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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;
|
||||
}
|
||||
|
688
0441-pid1-add-new-Type-notify-reload-service-type.patch
Normal file
688
0441-pid1-add-new-Type-notify-reload-service-type.patch
Normal file
@ -0,0 +1,688 @@
|
||||
From f64d331351e33199c4096b2ae4a4b9d24d127661 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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 {
|
||||
|
||||
<!--property OOMPolicy is not documented!-->
|
||||
|
||||
+ <!--property ReloadSignal is not documented!-->
|
||||
+
|
||||
<!--property ExecCondition is not documented!-->
|
||||
|
||||
<!--property ExecConditionEx is not documented!-->
|
||||
@@ -3715,6 +3719,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="OOMPolicy"/>
|
||||
|
||||
+ <variablelist class="dbus-property" generated="True" extra-ref="ReloadSignal"/>
|
||||
+
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ExecMainStartTimestamp"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="ExecMainStartTimestampMonotonic"/>
|
||||
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;
|
420
0442-man-document-Type-notify-reload.patch
Normal file
420
0442-man-document-Type-notify-reload.patch
Normal file
@ -0,0 +1,420 @@
|
||||
From e8de964c146f67c91acdaff076420282c2d1b217 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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 @@
|
||||
<varlistentry>
|
||||
<term>READY=1</term>
|
||||
|
||||
- <listitem><para>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 <varname>Type=notify</varname>
|
||||
- set. Since there is little value in signaling non-readiness, the only value services should send is
|
||||
- <literal>READY=1</literal> (i.e. <literal>READY=0</literal> is not defined).</para></listitem>
|
||||
+ <listitem><para>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
|
||||
+ <varname>Type=notify</varname> or <varname>Type=notify-reload</varname> set. Since there is little
|
||||
+ value in signaling non-readiness, the only value services should send is <literal>READY=1</literal>
|
||||
+ (i.e. <literal>READY=0</literal> is not defined).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>RELOADING=1</term>
|
||||
|
||||
- <listitem><para>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 <literal>READY=1</literal>
|
||||
- notification when it completed reloading its
|
||||
- configuration. Reloads are propagated in the same way as they
|
||||
- are when initiated by the user.</para></listitem>
|
||||
+ <listitem><para>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
|
||||
+ <literal>READY=1</literal> 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
|
||||
+ <varname>Type=notify-reload</varname> services, to inform the service manager that the request to
|
||||
+ reload the service has been received and is now being processed.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term>MONOTONIC_USEC=…</term>
|
||||
+
|
||||
+ <listitem><para>A field carrying the monotonic timestamp (as per
|
||||
+ <constant>CLOCK_MONOTONIC</constant>) formatted in decimal in µs, when the notification message was
|
||||
+ generated by the client. This is typically used in combination with <literal>RELOADING=1</literal>,
|
||||
+ to allow the service manager to properly synchronize reload cycles. See
|
||||
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
+ for details, specifically <literal>Type=notify-reload</literal>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
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 @@
|
||||
<listitem>
|
||||
<para>Configures the process start-up type for this service unit. One of <option>simple</option>,
|
||||
<option>exec</option>, <option>forking</option>, <option>oneshot</option>, <option>dbus</option>,
|
||||
- <option>notify</option> or <option>idle</option>:</para>
|
||||
+ <option>notify</option>, <option>notify-reload</option> or <option>idle</option>:</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem><para>If set to <option>simple</option> (the default if <varname>ExecStart=</varname> is
|
||||
@@ -216,14 +216,30 @@
|
||||
logic thus should be prepared to receive a <constant>SIGTERM</constant> (or whichever signal is
|
||||
configured in <varname>KillSignal=</varname>) as result.</para></listitem>
|
||||
|
||||
- <listitem><para>Behavior of <option>notify</option> is similar to <option>exec</option>; however, it is
|
||||
- expected that the service sends a notification message via
|
||||
- <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> 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, <varname>NotifyAccess=</varname> (see
|
||||
- below) should be set to open access to the notification socket provided by systemd. If
|
||||
- <varname>NotifyAccess=</varname> is missing or set to <option>none</option>, it will be forcibly set to
|
||||
- <option>main</option>.</para></listitem>
|
||||
+ <listitem><para>Behavior of <option>notify</option> is similar to <option>exec</option>; however,
|
||||
+ it is expected that the service sends a <literal>READY=1</literal> notification message via
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> 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,
|
||||
+ <varname>NotifyAccess=</varname> (see below) should be set to open access to the notification
|
||||
+ socket provided by systemd. If <varname>NotifyAccess=</varname> is missing or set to
|
||||
+ <option>none</option>, it will be forcibly set to <option>main</option>.</para></listitem>
|
||||
+
|
||||
+ <listitem><para>Behavior of <option>notify-reload</option> is identical to
|
||||
+ <option>notify</option>. However, it extends the logic in one way: the
|
||||
+ <constant>SIGHUP</constant> 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
|
||||
+ <varname>ReloadSignal=</varname>, see below.). When
|
||||
+ initiating the reload process the service is then expected to reply with a notification message
|
||||
+ via <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
+ that contains the <literal>RELOADING=1</literal> field in combination with
|
||||
+ <literal>MONOTONIC_USEC=</literal> set to the current monotonic time
|
||||
+ (i.e. <constant>CLOCK_MONOTONIC</constant> in
|
||||
+ <citerefentry><refentrytitle>clock_gettime</refentrytitle><manvolnum>2</manvolnum></citerefentry>)
|
||||
+ in µs, formatted as decimal string. Once reloading is complete another notification message must
|
||||
+ be sent, containing <literal>READY=1</literal>. Using this service type and implementing this
|
||||
+ reload protocol is an efficient alternative to providing an <varname>ExecReload=</varname>
|
||||
+ command for reloading of the service's configuration.</para></listitem>
|
||||
|
||||
<listitem><para>Behavior of <option>idle</option> is very similar to <option>simple</option>; however,
|
||||
actual execution of the service program is delayed until all active jobs are dispatched. This may be used
|
||||
@@ -233,25 +249,27 @@
|
||||
anyway.</para></listitem>
|
||||
</itemizedlist>
|
||||
|
||||
- <para>It is generally recommended to use <varname>Type=</varname><option>simple</option> 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,
|
||||
- <option>notify</option> or <option>dbus</option> (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
|
||||
- <option>notify</option> service type requires explicit support in the service codebase (as
|
||||
- <function>sd_notify()</function> or an equivalent API needs to be invoked by the service at the appropriate
|
||||
- time) — if it's not supported, then <option>forking</option> is an alternative: it supports the traditional
|
||||
- UNIX service start-up protocol. Finally, <option>exec</option> 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
|
||||
- <option>simple</option> 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
|
||||
- <option>simple</option>. (Also note it is generally not recommended to use <option>idle</option> or
|
||||
- <option>oneshot</option> for long-running services.)</para>
|
||||
+ <para>It is generally recommended to use <varname>Type=</varname><option>simple</option> 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, <option>notify</option>,
|
||||
+ <option>notify-reload</option> or <option>dbus</option> (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 <option>notify</option>/<option>notify-reload</option> service types require
|
||||
+ explicit support in the service codebase (as <function>sd_notify()</function> or an equivalent API
|
||||
+ needs to be invoked by the service at the appropriate time) — if it's not supported, then
|
||||
+ <option>forking</option> is an alternative: it supports the traditional UNIX service start-up
|
||||
+ protocol. Finally, <option>exec</option> 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 <option>simple</option> 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 <option>simple</option>. (Also note it is generally not recommended to use
|
||||
+ <option>idle</option> or <option>oneshot</option> for long-running services.)</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -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.</para>
|
||||
|
||||
- <para>Note that PID files should be avoided in modern projects. Use <option>Type=notify</option> or
|
||||
- <option>Type=simple</option> where possible, which does not require use of PID files to determine the
|
||||
- main process of a service and avoids needless forking.</para></listitem>
|
||||
+ <para>Note that PID files should be avoided in modern projects. Use <option>Type=notify</option>,
|
||||
+ <option>Type=notify-reload</option> or <option>Type=simple</option> where possible, which does not
|
||||
+ require use of PID files to determine the main process of a service and avoids needless
|
||||
+ forking.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -443,12 +462,13 @@
|
||||
with a <literal>-</literal> exit successfully.</para>
|
||||
|
||||
<para><varname>ExecStartPost=</varname> commands are only run after the commands specified in
|
||||
- <varname>ExecStart=</varname> have been invoked successfully, as determined by <varname>Type=</varname>
|
||||
- (i.e. the process has been started for <varname>Type=simple</varname> or <varname>Type=idle</varname>, the last
|
||||
- <varname>ExecStart=</varname> process exited successfully for <varname>Type=oneshot</varname>, the initial
|
||||
- process exited successfully for <varname>Type=forking</varname>, <literal>READY=1</literal> is sent for
|
||||
- <varname>Type=notify</varname>, or the <varname>BusName=</varname> has been taken for
|
||||
- <varname>Type=dbus</varname>).</para>
|
||||
+ <varname>ExecStart=</varname> have been invoked successfully, as determined by
|
||||
+ <varname>Type=</varname> (i.e. the process has been started for <varname>Type=simple</varname> or
|
||||
+ <varname>Type=idle</varname>, the last <varname>ExecStart=</varname> process exited successfully for
|
||||
+ <varname>Type=oneshot</varname>, the initial process exited successfully for
|
||||
+ <varname>Type=forking</varname>, <literal>READY=1</literal> is sent for
|
||||
+ <varname>Type=notify</varname>/<varname>Type=notify-reload</varname>, or the
|
||||
+ <varname>BusName=</varname> has been taken for <varname>Type=dbus</varname>).</para>
|
||||
|
||||
<para>Note that <varname>ExecStartPre=</varname> may not be
|
||||
used to start long-running processes. All processes forked
|
||||
@@ -487,30 +507,26 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>ExecReload=</varname></term>
|
||||
- <listitem><para>Commands to execute to trigger a configuration
|
||||
- reload in the service. This argument takes multiple command
|
||||
- lines, following the same scheme as described for
|
||||
- <varname>ExecStart=</varname> above. Use of this setting is
|
||||
- optional. Specifier and environment variable substitution is
|
||||
- supported here following the same scheme as for
|
||||
+
|
||||
+ <listitem><para>Commands to execute to trigger a configuration reload in the service. This argument
|
||||
+ takes multiple command lines, following the same scheme as described for
|
||||
+ <varname>ExecStart=</varname> above. Use of this setting is optional. Specifier and environment
|
||||
+ variable substitution is supported here following the same scheme as for
|
||||
<varname>ExecStart=</varname>.</para>
|
||||
|
||||
- <para>One additional, special environment variable is set: if
|
||||
- known, <varname>$MAINPID</varname> is set to the main process
|
||||
- of the daemon, and may be used for command lines like the
|
||||
- following:</para>
|
||||
+ <para>One additional, special environment variable is set: if known, <varname>$MAINPID</varname> is
|
||||
+ set to the main process of the daemon, and may be used for command lines like the following:</para>
|
||||
|
||||
<programlisting>ExecReload=kill -HUP $MAINPID</programlisting>
|
||||
|
||||
- <para>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
|
||||
- <varname>ExecReload=</varname> to a command that not only
|
||||
- triggers a configuration reload of the daemon, but also
|
||||
- synchronously waits for it to complete. For example,
|
||||
- <citerefentry project='mankier'><refentrytitle>dbus-broker</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
+ <para>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 <varname>Type=</varname><option>notify-reload</option> in place of
|
||||
+ <varname>ExecReload=</varname>, or to set <varname>ExecReload=</varname> to a command that not only
|
||||
+ triggers a configuration reload of the daemon, but also synchronously waits for it to complete. For
|
||||
+ example, <citerefentry
|
||||
+ project='mankier'><refentrytitle>dbus-broker</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
uses the following:</para>
|
||||
|
||||
<programlisting>ExecReload=busctl call org.freedesktop.DBus \
|
||||
@@ -605,12 +621,13 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
- <para>If a service of <varname>Type=notify</varname> sends <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause
|
||||
- the start time to be extended beyond <varname>TimeoutStartSec=</varname>. The first receipt of this message
|
||||
- must occur before <varname>TimeoutStartSec=</varname> is exceeded, and once the start time has extended beyond
|
||||
- <varname>TimeoutStartSec=</varname>, the service manager will allow the service to continue to start, provided
|
||||
- the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified until the service
|
||||
- startup status is finished by <literal>READY=1</literal>. (see
|
||||
+ <para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> sends
|
||||
+ <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause the start time to be extended beyond
|
||||
+ <varname>TimeoutStartSec=</varname>. The first receipt of this message must occur before
|
||||
+ <varname>TimeoutStartSec=</varname> is exceeded, and once the start time has extended beyond
|
||||
+ <varname>TimeoutStartSec=</varname>, the service manager will allow the service to continue to start,
|
||||
+ provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified
|
||||
+ until the service startup status is finished by <literal>READY=1</literal>. (see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
@@ -633,12 +650,14 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
- <para>If a service of <varname>Type=notify</varname> sends <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause
|
||||
- the stop time to be extended beyond <varname>TimeoutStopSec=</varname>. The first receipt of this message
|
||||
- must occur before <varname>TimeoutStopSec=</varname> is exceeded, and once the stop time has extended beyond
|
||||
- <varname>TimeoutStopSec=</varname>, the service manager will allow the service to continue to stop, provided
|
||||
- the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified, or terminates itself
|
||||
- (see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
+ <para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> sends
|
||||
+ <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause the stop time to be extended beyond
|
||||
+ <varname>TimeoutStopSec=</varname>. The first receipt of this message must occur before
|
||||
+ <varname>TimeoutStopSec=</varname> is exceeded, and once the stop time has extended beyond
|
||||
+ <varname>TimeoutStopSec=</varname>, the service manager will allow the service to continue to stop,
|
||||
+ provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified,
|
||||
+ or terminates itself (see
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -661,13 +680,15 @@
|
||||
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
|
||||
</para>
|
||||
|
||||
- <para>If a service of <varname>Type=notify</varname> handles <constant>SIGABRT</constant> itself (instead of relying
|
||||
- on the kernel to write a core dump) it can send <literal>EXTEND_TIMEOUT_USEC=…</literal> to
|
||||
- extended the abort time beyond <varname>TimeoutAbortSec=</varname>. The first receipt of this message
|
||||
- must occur before <varname>TimeoutAbortSec=</varname> is exceeded, and once the abort time has extended beyond
|
||||
- <varname>TimeoutAbortSec=</varname>, the service manager will allow the service to continue to abort, provided
|
||||
- the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified, or terminates itself
|
||||
- (see <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
+ <para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> handles
|
||||
+ <constant>SIGABRT</constant> itself (instead of relying on the kernel to write a core dump) it can
|
||||
+ send <literal>EXTEND_TIMEOUT_USEC=…</literal> to extended the abort time beyond
|
||||
+ <varname>TimeoutAbortSec=</varname>. The first receipt of this message must occur before
|
||||
+ <varname>TimeoutAbortSec=</varname> is exceeded, and once the abort time has extended beyond
|
||||
+ <varname>TimeoutAbortSec=</varname>, the service manager will allow the service to continue to abort,
|
||||
+ provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified,
|
||||
+ or terminates itself (see
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -710,12 +731,13 @@
|
||||
activation completed. Pass <literal>infinity</literal> (the default) to configure no runtime
|
||||
limit.</para>
|
||||
|
||||
- <para>If a service of <varname>Type=notify</varname> sends <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause
|
||||
- the runtime to be extended beyond <varname>RuntimeMaxSec=</varname>. The first receipt of this message
|
||||
- must occur before <varname>RuntimeMaxSec=</varname> is exceeded, and once the runtime has extended beyond
|
||||
- <varname>RuntimeMaxSec=</varname>, the service manager will allow the service to continue to run, provided
|
||||
- the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified until the service
|
||||
- shutdown is achieved by <literal>STOPPING=1</literal> (or termination). (see
|
||||
+ <para>If a service of <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> sends
|
||||
+ <literal>EXTEND_TIMEOUT_USEC=…</literal>, this may cause the runtime to be extended beyond
|
||||
+ <varname>RuntimeMaxSec=</varname>. The first receipt of this message must occur before
|
||||
+ <varname>RuntimeMaxSec=</varname> is exceeded, and once the runtime has extended beyond
|
||||
+ <varname>RuntimeMaxSec=</varname>, the service manager will allow the service to continue to run,
|
||||
+ provided the service repeats <literal>EXTEND_TIMEOUT_USEC=…</literal> within the interval specified
|
||||
+ until the service shutdown is achieved by <literal>STOPPING=1</literal> (or termination). (see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>).
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
@@ -1023,16 +1045,19 @@
|
||||
<varlistentry>
|
||||
<term><varname>NotifyAccess=</varname></term>
|
||||
<listitem><para>Controls access to the service status notification socket, as accessible via the
|
||||
- <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry> call. Takes one
|
||||
- of <option>none</option> (the default), <option>main</option>, <option>exec</option> or
|
||||
- <option>all</option>. If <option>none</option>, no daemon status updates are accepted from the service
|
||||
- processes, all status update messages are ignored. If <option>main</option>, only service updates sent from the
|
||||
- main process of the service are accepted. If <option>exec</option>, only service updates sent from any of the
|
||||
- main or control processes originating from one of the <varname>Exec*=</varname> commands are accepted. If
|
||||
- <option>all</option>, 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 <varname>Type=notify</varname> or
|
||||
- <varname>WatchdogSec=</varname> (see above). If those options are used but <varname>NotifyAccess=</varname> is
|
||||
- not configured, it will be implicitly set to <option>main</option>.</para>
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
+ call. Takes one of <option>none</option> (the default), <option>main</option>, <option>exec</option>
|
||||
+ or <option>all</option>. If <option>none</option>, no daemon status updates are accepted from the
|
||||
+ service processes, all status update messages are ignored. If <option>main</option>, only service
|
||||
+ updates sent from the main process of the service are accepted. If <option>exec</option>, only
|
||||
+ service updates sent from any of the main or control processes originating from one of the
|
||||
+ <varname>Exec*=</varname> commands are accepted. If <option>all</option>, 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
|
||||
+ <varname>Type=notify</varname>/<varname>Type=notify-reload</varname> or
|
||||
+ <varname>WatchdogSec=</varname> (see above). If those options are used but
|
||||
+ <varname>NotifyAccess=</varname> is not configured, it will be implicitly set to
|
||||
+ <option>main</option>.</para>
|
||||
|
||||
<para>Note that <function>sd_notify()</function> 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 <command>systemd-oomd</command> kills a
|
||||
cgroup associated with it.</para></listitem>
|
||||
</varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><varname>ReloadSignal=</varname></term>
|
||||
+ <listitem><para>Configures the UNIX process signal to send to the service's main process when asked
|
||||
+ to reload the service's configuration. Defaults to <constant>SIGHUP</constant>. This option has no
|
||||
+ effect unless <varname>Type=</varname><option>notify-reload</option> is used, see
|
||||
+ above.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
</variablelist>
|
||||
|
||||
<para id='shared-unit-options'>Check
|
||||
@@ -1319,16 +1353,13 @@ WantedBy=multi-user.target</programlisting>
|
||||
<citerefentry><refentrytitle>systemd.kill</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
for details.</para>
|
||||
|
||||
- <para>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
|
||||
- <varname>Type=</varname><option>notify</option> if the service
|
||||
- understands systemd's notification protocol,
|
||||
- <varname>Type=</varname><option>forking</option> if the service
|
||||
- can background itself or
|
||||
- <varname>Type=</varname><option>dbus</option> if the unit
|
||||
- acquires a DBus name once initialization is complete. See
|
||||
- below.</para>
|
||||
+ <para>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
|
||||
+ <varname>Type=</varname><option>notify</option>/<varname>Type=</varname><option>notify-reload</option>
|
||||
+ if the service understands systemd's notification protocol,
|
||||
+ <varname>Type=</varname><option>forking</option> if the service can background itself or
|
||||
+ <varname>Type=</varname><option>dbus</option> if the unit acquires a DBus name once initialization is
|
||||
+ complete. See below.</para>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
@@ -1505,15 +1536,12 @@ SystemdService=simple-dbus-service.service</programlisting>
|
||||
<example>
|
||||
<title>Services that notify systemd about their initialization</title>
|
||||
|
||||
- <para><varname>Type=</varname><option>simple</option> 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
|
||||
- <varname>Type=</varname><option>notify</option> for this. A
|
||||
- typical service file for such a daemon would look like
|
||||
- this:</para>
|
||||
+ <para><varname>Type=</varname><option>simple</option> 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 <varname>Type=</varname><option>notify</option> or
|
||||
+ <varname>Type=</varname><option>notify-reload</option> for this. A typical service file for such a
|
||||
+ daemon would look like this:</para>
|
||||
|
||||
<programlisting>[Unit]
|
||||
Description=Simple notifying service
|
105
0443-pid1-make-sure-we-send-our-calling-service-manager-R.patch
Normal file
105
0443-pid1-make-sure-we-send-our-calling-service-manager-R.patch
Normal file
@ -0,0 +1,105 @@
|
||||
From 567b6dcd4ff8e4a9c9b0b1629fa8c015d5e6a724 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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
|
166
0444-networkd-implement-Type-notify-reload-protocol.patch
Normal file
166
0444-networkd-implement-Type-notify-reload-protocol.patch
Normal file
@ -0,0 +1,166 @@
|
||||
From fef242735b987c1870bcd0460cc0c802e78a3cde Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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}}
|
||||
|
127
0445-udevd-implement-the-full-Type-notify-reload-protocol.patch
Normal file
127
0445-udevd-implement-the-full-Type-notify-reload-protocol.patch
Normal file
@ -0,0 +1,127 @@
|
||||
From daa0a0268e9ed03b8e3c39f003266d0b14cae120 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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
|
@ -0,0 +1,52 @@
|
||||
From dd9aa5ffe940ac6d5204a04fce5faafc3fc01924 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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
|
297
0447-notify-add-stopping-reloading-switches.patch
Normal file
297
0447-notify-add-stopping-reloading-switches.patch
Normal file
@ -0,0 +1,297 @@
|
||||
From 2b5c9fceaaa30ec9c2d031c9ca32b71c43f22f98 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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 @@
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
- <para><command>systemd-notify</command> 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.</para>
|
||||
-
|
||||
- <para>This is mostly just a wrapper around
|
||||
- <function>sd_notify()</function> and makes this functionality
|
||||
+ <para><command>systemd-notify</command> 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.</para>
|
||||
+
|
||||
+ <para>This is mostly just a wrapper around <function>sd_notify()</function> and makes this functionality
|
||||
available to shell scripts. For details see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
- <para>The command line may carry a list of environment variables
|
||||
- to send as part of the status update.</para>
|
||||
+ <para>The command line may carry a list of environment variables to send as part of the status
|
||||
+ update.</para>
|
||||
|
||||
<para>Note that systemd will refuse reception of status updates from this command unless
|
||||
<varname>NotifyAccess=</varname> is set for the service unit this command is called from.</para>
|
||||
|
||||
- <para>Note that <function>sd_notify()</function> 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 <varname>NotifyAccess=</varname><option>main</option> or
|
||||
- <varname>NotifyAccess=</varname><option>exec</option>. Conversely, if an auxiliary process of the unit sends an
|
||||
- <function>sd_notify()</function> 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 <varname>NotifyAccess=</varname><option>all
|
||||
- </option> is set for it. When <option>--no-block</option> 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.</para>
|
||||
+ <para>Note that <function>sd_notify()</function> 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
|
||||
+ <varname>NotifyAccess=</varname><option>main</option> or
|
||||
+ <varname>NotifyAccess=</varname><option>exec</option>. Conversely, if an auxiliary process of the unit
|
||||
+ sends an <function>sd_notify()</function> 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
|
||||
+ <varname>NotifyAccess=</varname><option>all</option> is set for it. To address this
|
||||
+ <command>systemd-notify</command> will wait until the notification message has been processed by the
|
||||
+ service manager. When <option>--no-block</option> 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.</para>
|
||||
|
||||
<para>Hence, <command>systemd-notify</command> will first attempt to invoke <function>sd_notify()</function>
|
||||
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 <varname>NotifyAccess=</varname><option>all</option>. Use the <option>--pid=</option>
|
||||
switch to tweak this behaviour.</para>
|
||||
-
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@@ -78,22 +78,42 @@
|
||||
<varlistentry>
|
||||
<term><option>--ready</option></term>
|
||||
|
||||
- <listitem><para>Inform the init system about service start-up
|
||||
- completion. This is equivalent to <command>systemd-notify
|
||||
- READY=1</command>. For details about the semantics of this
|
||||
- option see
|
||||
+ <listitem><para>Inform the invoking service manager about service start-up or configuration reload
|
||||
+ completion. This is equivalent to <command>systemd-notify READY=1</command>. For details about the
|
||||
+ semantics of this option see
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><option>--reloading</option></term>
|
||||
+
|
||||
+ <listitem><para>Inform the invoking service manager about the beginning of a configuration reload
|
||||
+ cycle. This is equivalent to <command>systemd-notify RELOADING=1</command> (but implicitly also sets
|
||||
+ a <varname>MONOTONIC_USEC=</varname> field as required for <varname>Type=notify-reload</varname>
|
||||
+ services, see
|
||||
+ <citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
|
||||
+ for details). For details about the semantics of this option see
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
+ </varlistentry>
|
||||
+
|
||||
+ <varlistentry>
|
||||
+ <term><option>--stopping</option></term>
|
||||
+
|
||||
+ <listitem><para>Inform the invoking service manager about the beginning of the shutdown phase of the
|
||||
+ service. This is equivalent to <command>systemd-notify STOPPING=1</command>. For details about the
|
||||
+ semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--pid=</option></term>
|
||||
|
||||
- <listitem><para>Inform the service manager about the main PID of the daemon. Takes a PID as
|
||||
+ <listitem><para>Inform the service manager about the main PID of the service. Takes a PID as
|
||||
argument. If the argument is specified as <literal>auto</literal> or omitted, the PID of the process
|
||||
that invoked <command>systemd-notify</command> is used, except if that's the service manager. If the
|
||||
argument is specified as <literal>self</literal>, the PID of the <command>systemd-notify</command>
|
||||
command itself is used, and if <literal>parent</literal> is specified the calling process' PID is
|
||||
- used — even if it is the service manager. This is equivalent to <command>systemd-notify
|
||||
+ used — even if it is the service manager. The latter is equivalent to <command>systemd-notify
|
||||
MAINPID=$PID</command>. For details about the semantics of this option see
|
||||
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
</varlistentry>
|
||||
@@ -110,27 +130,26 @@
|
||||
<varlistentry>
|
||||
<term><option>--status=</option></term>
|
||||
|
||||
- <listitem><para>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 <command>systemd-notify
|
||||
- STATUS=…</command>. For details about the semantics of this
|
||||
- option see
|
||||
- <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.</para></listitem>
|
||||
+ <listitem><para>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
|
||||
+ <command>systemd-notify STATUS=…</command>. For details about the semantics of this option see
|
||||
+ <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>. This
|
||||
+ information is shown in
|
||||
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
+ <command>status</command> output, among other places.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--booted</option></term>
|
||||
|
||||
- <listitem><para>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
|
||||
+ <listitem><para>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
|
||||
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>. An
|
||||
alternate way to check for this state is to call
|
||||
- <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
- with the <command>is-system-running</command> command. It will
|
||||
- return <literal>offline</literal> if the system was not booted
|
||||
- with systemd. </para></listitem>
|
||||
+ <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry> with
|
||||
+ the <command>is-system-running</command> command. It will return <literal>offline</literal> if the
|
||||
+ system was not booted with systemd. </para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@@ -162,9 +181,8 @@
|
||||
<example>
|
||||
<title>Start-up Notification and Status Updates</title>
|
||||
|
||||
- <para>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:</para>
|
||||
+ <para>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:</para>
|
||||
|
||||
<programlisting>#!/bin/sh
|
||||
|
||||
@@ -192,5 +210,4 @@ done</programlisting>
|
||||
<citerefentry><refentrytitle>sd_booted</refentrytitle><manvolnum>3</manvolnum></citerefentry>
|
||||
</para>
|
||||
</refsect1>
|
||||
-
|
||||
</refentry>
|
||||
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)
|
74
0448-test-add-Type-notify-reload-testcase.patch
Normal file
74
0448-test-add-Type-notify-reload-testcase.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From 3a2cb37fdbe4e761ae649716f6f8f71feffdd608 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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 <<EOF
|
||||
+#!/usr/bin/env bash
|
||||
+set -eux
|
||||
+set -o pipefail
|
||||
+
|
||||
+EXIT_STATUS=88
|
||||
+LEAVE=0
|
||||
+
|
||||
+function reload() {
|
||||
+ systemd-notify --reloading --status="Adding 11 to exit status"
|
||||
+ EXIT_STATUS=\$((\$EXIT_STATUS + 11))
|
||||
+ systemd-notify --ready --status="Back running"
|
||||
+}
|
||||
+
|
||||
+function leave() {
|
||||
+ systemd-notify --stopping --status="Adding 7 to exit status"
|
||||
+ EXIT_STATUS=\$((\$EXIT_STATUS + 7))
|
||||
+ LEAVE=1
|
||||
+ return 0
|
||||
+}
|
||||
+
|
||||
+trap reload SIGHUP
|
||||
+trap leave SIGTERM
|
||||
+
|
||||
+systemd-notify --ready
|
||||
+systemd-notify --status="Running now"
|
||||
+
|
||||
+while [ \$LEAVE = 0 ] ; do
|
||||
+ sleep 1
|
||||
+done
|
||||
+
|
||||
+systemd-notify --status="Adding 3 to exit status"
|
||||
+EXIT_STATUS=\$((\$EXIT_STATUS + 3))
|
||||
+exit \$EXIT_STATUS
|
||||
+EOF
|
||||
+
|
||||
+chmod +x /run/notify-reload-test.sh
|
||||
+
|
||||
+systemd-analyze log-level debug
|
||||
+
|
||||
+systemd-run --unit notify-reload-test -p Type=notify-reload -p KillMode=process /run/notify-reload-test.sh
|
||||
+systemctl reload notify-reload-test
|
||||
+systemctl stop notify-reload-test
|
||||
+
|
||||
+test "$(systemctl show -p ExecMainStatus --value notify-reload-test)" = 109
|
||||
+
|
||||
+systemctl reset-failed notify-reload-test
|
||||
+rm /run/notify-reload-test.sh
|
||||
+
|
||||
systemd-analyze log-level info
|
||||
|
||||
echo OK >/testok
|
45
0449-update-TODO.patch
Normal file
45
0449-update-TODO.patch
Normal file
@ -0,0 +1,45 @@
|
||||
From 3fa498dba2e67c1c97f25b093ec6c36e55023259 Mon Sep 17 00:00:00 2001
|
||||
From: Lennart Poettering <lennart@poettering.net>
|
||||
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=
|
@ -0,0 +1,40 @@
|
||||
From 036f0593b33ddc0f40a333d790a276c3cffe862e Mon Sep 17 00:00:00 2001
|
||||
From: msizanoen1 <msizanoen@qtmlabs.xyz>
|
||||
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;
|
42
systemd.spec
42
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 <systemd-maint@redhat.com> - 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 <systemd-maint@redhat.com> - 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)
|
||||
|
Loading…
Reference in New Issue
Block a user