|
|
613b6e |
From da81a108653e2ef19102698dbc0184bd18b084d9 Mon Sep 17 00:00:00 2001
|
|
|
613b6e |
From: Mike Yuan <me@yhndnzj.com>
|
|
|
613b6e |
Date: Thu, 10 Oct 2024 21:16:05 +0200
|
|
|
613b6e |
Subject: [PATCH 1/4] core/manager: still send out STATUS=Ready for user
|
|
|
613b6e |
manager
|
|
|
613b6e |
|
|
|
613b6e |
This effectively reverts 37d15cd132f3a8a0bf42fb252c1604e804171ff2.
|
|
|
613b6e |
|
|
|
613b6e |
The offending commit wrongly assumed that the second READY=1
|
|
|
613b6e |
notification is for system scope only, but it also serves the purpose
|
|
|
613b6e |
of flushing out previous STATUS= containing user unit job status.
|
|
|
613b6e |
---
|
|
|
613b6e |
src/core/manager.c | 14 +++++++-------
|
|
|
613b6e |
1 file changed, 7 insertions(+), 7 deletions(-)
|
|
|
613b6e |
|
|
|
613b6e |
diff --git a/src/core/manager.c b/src/core/manager.c
|
|
|
613b6e |
index 2789f0e3d0c9c..456ad46135b72 100644
|
|
|
613b6e |
--- a/src/core/manager.c
|
|
|
613b6e |
+++ b/src/core/manager.c
|
|
|
613b6e |
@@ -3885,7 +3885,7 @@ static void manager_notify_finished(Manager *m) {
|
|
|
613b6e |
log_taint_string(m);
|
|
|
613b6e |
}
|
|
|
613b6e |
|
|
|
613b6e |
-static void manager_send_ready_user_scope(Manager *m) {
|
|
|
613b6e |
+static void manager_send_ready_on_basic_target(Manager *m) {
|
|
|
613b6e |
int r;
|
|
|
613b6e |
|
|
|
613b6e |
assert(m);
|
|
|
613b6e |
@@ -3904,18 +3904,18 @@ static void manager_send_ready_user_scope(Manager *m) {
|
|
|
613b6e |
m->status_ready = false;
|
|
|
613b6e |
}
|
|
|
613b6e |
|
|
|
613b6e |
-static void manager_send_ready_system_scope(Manager *m) {
|
|
|
613b6e |
+static void manager_send_ready_on_idle(Manager *m) {
|
|
|
613b6e |
int r;
|
|
|
613b6e |
|
|
|
613b6e |
assert(m);
|
|
|
613b6e |
|
|
|
613b6e |
- if (!MANAGER_IS_SYSTEM(m))
|
|
|
613b6e |
- return;
|
|
|
613b6e |
-
|
|
|
613b6e |
/* Skip the notification if nothing changed. */
|
|
|
613b6e |
if (m->ready_sent && m->status_ready)
|
|
|
613b6e |
return;
|
|
|
613b6e |
|
|
|
613b6e |
+ /* Note that for user managers, we might have already sent READY=1 in manager_send_ready_user_scope().
|
|
|
613b6e |
+ * But we still need to flush STATUS=. The second READY=1 will be treated as a noop so it doesn't
|
|
|
613b6e |
+ * hurt to send it twice. */
|
|
|
613b6e |
r = sd_notify(/* unset_environment= */ false,
|
|
|
613b6e |
"READY=1\n"
|
|
|
613b6e |
"STATUS=Ready.");
|
|
|
613b6e |
@@ -3940,7 +3940,7 @@ static void manager_check_basic_target(Manager *m) {
|
|
|
613b6e |
return;
|
|
|
613b6e |
|
|
|
613b6e |
/* For user managers, send out READY=1 as soon as we reach basic.target */
|
|
|
613b6e |
- manager_send_ready_user_scope(m);
|
|
|
613b6e |
+ manager_send_ready_on_basic_target(m);
|
|
|
613b6e |
|
|
|
613b6e |
/* Log the taint string as soon as we reach basic.target */
|
|
|
613b6e |
log_taint_string(m);
|
|
|
613b6e |
@@ -3971,7 +3971,7 @@ void manager_check_finished(Manager *m) {
|
|
|
613b6e |
if (hashmap_buckets(m->jobs) > hashmap_size(m->units) / 10)
|
|
|
613b6e |
m->jobs = hashmap_free(m->jobs);
|
|
|
613b6e |
|
|
|
613b6e |
- manager_send_ready_system_scope(m);
|
|
|
613b6e |
+ manager_send_ready_on_idle(m);
|
|
|
613b6e |
|
|
|
613b6e |
/* Notify Type=idle units that we are done now */
|
|
|
613b6e |
manager_close_idle_pipe(m);
|
|
|
613b6e |
|
|
|
613b6e |
From 155098a702c4f6de6b1dca534661492625773fed Mon Sep 17 00:00:00 2001
|
|
|
613b6e |
From: Mike Yuan <me@yhndnzj.com>
|
|
|
613b6e |
Date: Thu, 10 Oct 2024 21:06:35 +0200
|
|
|
613b6e |
Subject: [PATCH 2/4] core/manager-serialize: drop serialization for
|
|
|
613b6e |
Manager.ready_sent
|
|
|
613b6e |
|
|
|
613b6e |
This field indicates whether READY=1 has been sent to
|
|
|
613b6e |
the service manager/supervisor. Whenever we reload/reexec/soft-reboot,
|
|
|
613b6e |
manager_send_reloading() always resets it to false first,
|
|
|
613b6e |
so that READY=1 is sent after reloading finishes. Hence
|
|
|
613b6e |
we utterly get "false" at all times. Kill it.
|
|
|
613b6e |
---
|
|
|
613b6e |
src/core/manager-serialize.c | 12 +-----------
|
|
|
613b6e |
1 file changed, 1 insertion(+), 11 deletions(-)
|
|
|
613b6e |
|
|
|
613b6e |
diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c
|
|
|
613b6e |
index 62dfce93a0a85..3f624619dfd19 100644
|
|
|
613b6e |
--- a/src/core/manager-serialize.c
|
|
|
613b6e |
+++ b/src/core/manager-serialize.c
|
|
|
613b6e |
@@ -92,7 +92,6 @@ int manager_serialize(
|
|
|
613b6e |
(void) serialize_item_format(f, "current-job-id", "%" PRIu32, m->current_job_id);
|
|
|
613b6e |
(void) serialize_item_format(f, "n-installed-jobs", "%u", m->n_installed_jobs);
|
|
|
613b6e |
(void) serialize_item_format(f, "n-failed-jobs", "%u", m->n_failed_jobs);
|
|
|
613b6e |
- (void) serialize_bool(f, "ready-sent", m->ready_sent);
|
|
|
613b6e |
(void) serialize_bool(f, "taint-logged", m->taint_logged);
|
|
|
613b6e |
(void) serialize_bool(f, "service-watchdogs", m->service_watchdogs);
|
|
|
613b6e |
|
|
|
613b6e |
@@ -356,15 +355,6 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|
|
613b6e |
else
|
|
|
613b6e |
m->n_failed_jobs += n;
|
|
|
613b6e |
|
|
|
613b6e |
- } else if ((val = startswith(l, "ready-sent="))) {
|
|
|
613b6e |
- int b;
|
|
|
613b6e |
-
|
|
|
613b6e |
- b = parse_boolean(val);
|
|
|
613b6e |
- if (b < 0)
|
|
|
613b6e |
- log_notice("Failed to parse ready-sent flag '%s', ignoring.", val);
|
|
|
613b6e |
- else
|
|
|
613b6e |
- m->ready_sent = m->ready_sent || b;
|
|
|
613b6e |
-
|
|
|
613b6e |
} else if ((val = startswith(l, "taint-logged="))) {
|
|
|
613b6e |
int b;
|
|
|
613b6e |
|
|
|
613b6e |
@@ -558,7 +548,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
|
|
|
613b6e |
|
|
|
613b6e |
if (q < _MANAGER_TIMESTAMP_MAX) /* found it */
|
|
|
613b6e |
(void) deserialize_dual_timestamp(val, m->timestamps + q);
|
|
|
613b6e |
- else if (!STARTSWITH_SET(l, "kdbus-fd=", "honor-device-enumeration=")) /* ignore deprecated values */
|
|
|
613b6e |
+ else if (!STARTSWITH_SET(l, "kdbus-fd=", "honor-device-enumeration=", "ready-sent=")) /* ignore deprecated values */
|
|
|
613b6e |
log_notice("Unknown serialization item '%s', ignoring.", l);
|
|
|
613b6e |
}
|
|
|
613b6e |
}
|
|
|
613b6e |
|
|
|
613b6e |
From a375e145190482e8a2f0971bffb332e31211622f Mon Sep 17 00:00:00 2001
|
|
|
613b6e |
From: Mike Yuan <me@yhndnzj.com>
|
|
|
613b6e |
Date: Thu, 10 Oct 2024 21:32:17 +0200
|
|
|
613b6e |
Subject: [PATCH 3/4] units/{user,capsule}@.service: issue daemon-reexec when
|
|
|
613b6e |
notify-reloading
|
|
|
613b6e |
|
|
|
613b6e |
Closes #28367 (but not really in the exact form, see below)
|
|
|
613b6e |
|
|
|
613b6e |
We have the problem of restarting all user manager instances
|
|
|
613b6e |
after upgrade. Current approaches involve systemctl kill
|
|
|
613b6e |
with SIGRTMIN+25, which is async and feels rather ugly [1][2];
|
|
|
613b6e |
or systemctl --machine=user@ --user, which requires entering
|
|
|
613b6e |
each user session. Neither is particularly elegant.
|
|
|
613b6e |
Instead, let's just signal daemon-reexec when user@.service
|
|
|
613b6e |
is reloaded from system manager. Our long goal of dropping
|
|
|
613b6e |
daemon-reload in favor of reexec (see TODO) is unlikely to happen
|
|
|
613b6e |
due to user dbus restrictions, but here the synchronization
|
|
|
613b6e |
is done via READY=1.
|
|
|
613b6e |
|
|
|
613b6e |
[1] https://gitlab.archlinux.org/archlinux/packaging/packages/systemd/-/blob/main/systemd.install?ref_type=heads#L37
|
|
|
613b6e |
[2] https://salsa.debian.org/systemd-team/systemd/-/blob/debian/master/debian/systemd.postinst#L24
|
|
|
613b6e |
|
|
|
613b6e |
#28367 would not really work for us now I come to think about it,
|
|
|
613b6e |
because all processes will be reparented to pid1 as soon as
|
|
|
613b6e |
original user manager process exits. This alternative approach
|
|
|
613b6e |
seems good enough for our use case.
|
|
|
613b6e |
---
|
|
|
613b6e |
units/capsule@.service.in | 4 ++++
|
|
|
613b6e |
units/user@.service.in | 4 ++++
|
|
|
613b6e |
2 files changed, 8 insertions(+)
|
|
|
613b6e |
|
|
|
613b6e |
diff --git a/units/capsule@.service.in b/units/capsule@.service.in
|
|
|
613b6e |
index f2bb9e3a45a83..a64298786e490 100644
|
|
|
613b6e |
--- a/units/capsule@.service.in
|
|
|
613b6e |
+++ b/units/capsule@.service.in
|
|
|
613b6e |
@@ -23,6 +23,10 @@ StateDirectory=capsules/%i
|
|
|
613b6e |
RuntimeDirectory=capsules/%i
|
|
|
613b6e |
LogExtraFields=CAPSULE=%i
|
|
|
613b6e |
Slice=capsule.slice
|
|
|
613b6e |
+# Reexecute the manager on service reload, instead of reloading.
|
|
|
613b6e |
+# This provides a synchronous method for restarting all user manager
|
|
|
613b6e |
+# instances after upgrade.
|
|
|
613b6e |
+ReloadSignal=RTMIN+25
|
|
|
613b6e |
KillMode=mixed
|
|
|
613b6e |
Delegate=pids memory cpu
|
|
|
613b6e |
DelegateSubgroup=init.scope
|
|
|
613b6e |
diff --git a/units/user@.service.in b/units/user@.service.in
|
|
|
613b6e |
index 5695465747217..381ab2a0db54e 100644
|
|
|
613b6e |
--- a/units/user@.service.in
|
|
|
613b6e |
+++ b/units/user@.service.in
|
|
|
613b6e |
@@ -20,6 +20,10 @@ PAMName=systemd-user
|
|
|
613b6e |
Type=notify-reload
|
|
|
613b6e |
ExecStart={{LIBEXECDIR}}/systemd --user
|
|
|
613b6e |
Slice=user-%i.slice
|
|
|
613b6e |
+# Reexecute the manager on service reload, instead of reloading.
|
|
|
613b6e |
+# This provides a synchronous method for restarting all user manager
|
|
|
613b6e |
+# instances after upgrade.
|
|
|
613b6e |
+ReloadSignal=RTMIN+25
|
|
|
613b6e |
KillMode=mixed
|
|
|
613b6e |
Delegate=pids memory cpu
|
|
|
613b6e |
DelegateSubgroup=init.scope
|
|
|
613b6e |
|
|
|
613b6e |
From 2d0af8bc354f4a1429cebedfb387af72c88720a0 Mon Sep 17 00:00:00 2001
|
|
|
613b6e |
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
|
|
613b6e |
Date: Thu, 10 Oct 2024 22:37:39 +0200
|
|
|
613b6e |
Subject: [PATCH 4/4] rpm/systemd-update-helper: Use systemctl reload to
|
|
|
613b6e |
reexec/reload user managers
|
|
|
613b6e |
|
|
|
613b6e |
Let's always use systemctl reload to reexec and reload user managers
|
|
|
613b6e |
now that it always implies a reexec. This moves all the job management
|
|
|
613b6e |
logic to pid 1 instead of bash and reduces the complexity of the logic
|
|
|
613b6e |
as we remove systemd-run, pam and systemd-stdio-bridge from the equation.
|
|
|
613b6e |
---
|
|
|
613b6e |
src/rpm/systemd-update-helper.in | 20 ++++----------------
|
|
|
613b6e |
1 file changed, 4 insertions(+), 16 deletions(-)
|
|
|
613b6e |
|
|
|
613b6e |
diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in
|
|
|
613b6e |
index c81e16c3d3ffb..8af914935261a 100755
|
|
|
613b6e |
--- a/src/rpm/systemd-update-helper.in
|
|
|
613b6e |
+++ b/src/rpm/systemd-update-helper.in
|
|
|
613b6e |
@@ -107,25 +107,13 @@ case "$command" in
|
|
|
613b6e |
|
|
|
613b6e |
[ -d /run/systemd/system ] || exit 0
|
|
|
613b6e |
|
|
|
613b6e |
- users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
|
|
|
613b6e |
-
|
|
|
613b6e |
- if [[ "$command" =~ reexec ]]; then
|
|
|
613b6e |
- for user in $users; do
|
|
|
613b6e |
- SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT_SEC}}s \
|
|
|
613b6e |
- systemctl --user -M "$user@" daemon-reexec &
|
|
|
613b6e |
- done
|
|
|
613b6e |
- wait
|
|
|
613b6e |
- fi
|
|
|
613b6e |
-
|
|
|
613b6e |
- if [[ "$command" =~ reload ]]; then
|
|
|
613b6e |
- for user in $users; do
|
|
|
613b6e |
- SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT_SEC}}s \
|
|
|
613b6e |
- systemctl --user -M "$user@" daemon-reload &
|
|
|
613b6e |
- done
|
|
|
613b6e |
- wait
|
|
|
613b6e |
+ if [[ "$command" =~ reexec|reload ]]; then
|
|
|
613b6e |
+ SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT_SEC}}s systemctl reload "user@*.service"
|
|
|
613b6e |
fi
|
|
|
613b6e |
|
|
|
613b6e |
if [[ "$command" =~ restart ]]; then
|
|
|
613b6e |
+ users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
|
|
|
613b6e |
+
|
|
|
613b6e |
for user in $users; do
|
|
|
613b6e |
SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT_SEC}}s \
|
|
|
613b6e |
systemctl --user -M "$user@" reload-or-restart --marked &
|