|
|
3e5297 |
From a63d5d320f81c1cbae07897a401ed5cc5374e0bf Mon Sep 17 00:00:00 2001
|
|
|
3e5297 |
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
|
|
|
3e5297 |
Date: Wed, 7 Jul 2021 14:37:57 +0200
|
|
|
3e5297 |
Subject: [PATCH 4/5] rpm: restart user services at the end of the transaction
|
|
|
3e5297 |
|
|
|
3e5297 |
This closes an important gap: so far we would reexecute the system manager and
|
|
|
3e5297 |
restart system services that were configured to do so, but we wouldn't do the
|
|
|
3e5297 |
same for user managers or user services.
|
|
|
3e5297 |
|
|
|
3e5297 |
The scheme used for user managers is very similar to the system one, except
|
|
|
3e5297 |
that there can be multiple user managers running, so we query the system
|
|
|
3e5297 |
manager to get a list of them, and then tell each one to do the equivalent
|
|
|
3e5297 |
operations: daemon-reload, disable --now, set-property Markers=+needs-restart,
|
|
|
3e5297 |
reload-or-restart --marked.
|
|
|
3e5297 |
|
|
|
3e5297 |
The total time that can be spend on this is bounded: we execute the commands in
|
|
|
3e5297 |
parallel over user managers and units, and additionally set SYSTEMD_BUS_TIMEOUT
|
|
|
3e5297 |
to a lower value (15 s by default). User managers should not have too many
|
|
|
3e5297 |
units running, and they should be able to do all those operations very
|
|
|
3e5297 |
quickly (<< 1s). The final restart operation may take longer, but it's done
|
|
|
3e5297 |
asynchronously, so we only wait for the queuing to happen.
|
|
|
3e5297 |
|
|
|
3e5297 |
The advantage of doing this synchronously is that we can wait for each step to
|
|
|
3e5297 |
happen, and for example daemon-reloads can finish before we execute the service
|
|
|
3e5297 |
restarts, etc. We can also order various steps wrt. to the phases in the rpm
|
|
|
3e5297 |
transaction.
|
|
|
3e5297 |
|
|
|
3e5297 |
When this was initially proposed, we discussed a more relaxed scheme with bus
|
|
|
3e5297 |
property notifications. Such an approach would be more complex because a bunch
|
|
|
3e5297 |
of infrastructure would have to be added to system manager to propagate
|
|
|
3e5297 |
appropriate notifications to the user managers, and then the user managers
|
|
|
3e5297 |
would have to wait for them. Instead, now there is no new code in the managers,
|
|
|
3e5297 |
all new functionality is contained in src/rpm/. The ability to call 'systemctl
|
|
|
3e5297 |
--user user@' makes this approach very easy. Also, it would be very hard to
|
|
|
3e5297 |
order the user manager steps and the rpm transaction steps.
|
|
|
3e5297 |
|
|
|
3e5297 |
Note: 'systemctl --user disable' is only called for a user managers that are
|
|
|
3e5297 |
running. I don't see a nice way around this, and it shouldn't matter too much:
|
|
|
3e5297 |
we'll just leave a dangling symlink in the case where the user enabled the
|
|
|
3e5297 |
service manually.
|
|
|
3e5297 |
|
|
|
3e5297 |
A follow-up for https://bugzilla.redhat.com/show_bug.cgi?id=1792468 and
|
|
|
3e5297 |
fa97d2fcf64e0558054bee673f734f523373b146.
|
|
|
3e5297 |
|
|
|
3e5297 |
(cherry picked from commit 36d55958ccc75fa3c91bdd7354d74c910f2f6cc7)
|
|
|
3e5297 |
---
|
|
|
3e5297 |
meson.build | 1 +
|
|
|
3e5297 |
meson_options.txt | 2 ++
|
|
|
3e5297 |
src/rpm/macros.systemd.in | 6 +++-
|
|
|
3e5297 |
src/rpm/systemd-update-helper.in | 47 ++++++++++++++++++++++++++++++++
|
|
|
3e5297 |
src/rpm/triggers.systemd.in | 28 ++++++++++++++++++-
|
|
|
3e5297 |
src/rpm/triggers.systemd.sh.in | 13 ++++++++-
|
|
|
3e5297 |
6 files changed, 94 insertions(+), 3 deletions(-)
|
|
|
3e5297 |
|
|
|
3e5297 |
diff --git a/meson.build b/meson.build
|
|
|
3e5297 |
index fb986e84f7..d898d9ccd0 100644
|
|
|
3e5297 |
--- a/meson.build
|
|
|
3e5297 |
+++ b/meson.build
|
|
|
3e5297 |
@@ -270,6 +270,7 @@ conf.set_quoted('TMPFILES_DIR', tmpfilesdir)
|
|
|
3e5297 |
conf.set_quoted('UDEVLIBEXECDIR', udevlibexecdir)
|
|
|
3e5297 |
conf.set_quoted('UDEV_HWDB_DIR', udevhwdbdir)
|
|
|
3e5297 |
conf.set_quoted('UDEV_RULES_DIR', udevrulesdir)
|
|
|
3e5297 |
+conf.set_quoted('UPDATE_HELPER_USER_TIMEOUT', get_option('update-helper-user-timeout'))
|
|
|
3e5297 |
conf.set_quoted('USER_CONFIG_UNIT_DIR', join_paths(pkgsysconfdir, 'user'))
|
|
|
3e5297 |
conf.set_quoted('USER_DATA_UNIT_DIR', userunitdir)
|
|
|
3e5297 |
conf.set_quoted('USER_ENV_GENERATOR_DIR', userenvgeneratordir)
|
|
|
3e5297 |
diff --git a/meson_options.txt b/meson_options.txt
|
|
|
3e5297 |
index 163c8df87d..9383c7da6a 100644
|
|
|
3e5297 |
--- a/meson_options.txt
|
|
|
3e5297 |
+++ b/meson_options.txt
|
|
|
3e5297 |
@@ -182,6 +182,8 @@ option('xinitrcdir', type : 'string', value : '',
|
|
|
3e5297 |
description : 'directory for xinitrc files')
|
|
|
3e5297 |
option('rpmmacrosdir', type : 'string', value : 'lib/rpm/macros.d',
|
|
|
3e5297 |
description : 'directory for rpm macros ["no" disables]')
|
|
|
3e5297 |
+option('update-helper-user-timeout', type : 'string', value : '15s',
|
|
|
3e5297 |
+ description : 'how long to wait for user manager operations')
|
|
|
3e5297 |
option('pamlibdir', type : 'string',
|
|
|
3e5297 |
description : 'directory for PAM modules')
|
|
|
3e5297 |
option('pamconfdir', type : 'string',
|
|
|
3e5297 |
diff --git a/src/rpm/macros.systemd.in b/src/rpm/macros.systemd.in
|
|
|
3e5297 |
index bbdf036da7..caa2e45595 100644
|
|
|
3e5297 |
--- a/src/rpm/macros.systemd.in
|
|
|
3e5297 |
+++ b/src/rpm/macros.systemd.in
|
|
|
3e5297 |
@@ -93,7 +93,11 @@ fi \
|
|
|
3e5297 |
%{nil}
|
|
|
3e5297 |
|
|
|
3e5297 |
%systemd_user_postun_with_restart() \
|
|
|
3e5297 |
-%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_postun_with_restart}} \
|
|
|
3e5297 |
+%{expand:%%{?__systemd_someargs_%#:%%__systemd_someargs_%# systemd_user_postun_with_restart}} \
|
|
|
3e5297 |
+if [ $1 -ge 1 ] && [ -x "{{SYSTEMD_UPDATE_HELPER_PATH}}" ]; then \
|
|
|
3e5297 |
+ # Package upgrade, not uninstall \
|
|
|
3e5297 |
+ {{SYSTEMD_UPDATE_HELPER_PATH}} mark-restart-user-units %{?*} || : \
|
|
|
3e5297 |
+fi \
|
|
|
3e5297 |
%{nil}
|
|
|
3e5297 |
|
|
|
3e5297 |
%udev_hwdb_update() %{nil}
|
|
|
3e5297 |
diff --git a/src/rpm/systemd-update-helper.in b/src/rpm/systemd-update-helper.in
|
|
|
3e5297 |
index f3c75b75fa..f3466ab3c0 100755
|
|
|
3e5297 |
--- a/src/rpm/systemd-update-helper.in
|
|
|
3e5297 |
+++ b/src/rpm/systemd-update-helper.in
|
|
|
3e5297 |
@@ -26,6 +26,15 @@ case "$command" in
|
|
|
3e5297 |
|
|
|
3e5297 |
remove-user-units)
|
|
|
3e5297 |
systemctl --global disable "$@"
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ [ -d /run/systemd/system ] || exit 0
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
|
|
|
3e5297 |
+ for user in $users; do
|
|
|
3e5297 |
+ SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
|
|
|
3e5297 |
+ systemctl --user -M "$user@" disable --now "$@" &
|
|
|
3e5297 |
+ done
|
|
|
3e5297 |
+ wait
|
|
|
3e5297 |
;;
|
|
|
3e5297 |
|
|
|
3e5297 |
mark-restart-system-units)
|
|
|
3e5297 |
@@ -37,6 +46,17 @@ case "$command" in
|
|
|
3e5297 |
wait
|
|
|
3e5297 |
;;
|
|
|
3e5297 |
|
|
|
3e5297 |
+ mark-restart-user-units)
|
|
|
3e5297 |
+ [ -d /run/systemd/system ] || exit 0
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
|
|
|
3e5297 |
+ for user in $users; do
|
|
|
3e5297 |
+ SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
|
|
|
3e5297 |
+ systemctl --user -M "$user@" set-property "$unit" Markers=+needs-restart &
|
|
|
3e5297 |
+ done
|
|
|
3e5297 |
+ wait
|
|
|
3e5297 |
+ ;;
|
|
|
3e5297 |
+
|
|
|
3e5297 |
system-reload-restart|system-reload|system-restart)
|
|
|
3e5297 |
if [ -n "$*" ]; then
|
|
|
3e5297 |
echo "Unexpected arguments for '$command': $*"
|
|
|
3e5297 |
@@ -54,6 +74,33 @@ case "$command" in
|
|
|
3e5297 |
fi
|
|
|
3e5297 |
;;
|
|
|
3e5297 |
|
|
|
3e5297 |
+ user-reload-restart|user-reload|user-restart)
|
|
|
3e5297 |
+ if [ -n "$*" ]; then
|
|
|
3e5297 |
+ echo "Unexpected arguments for '$command': $*"
|
|
|
3e5297 |
+ exit 2
|
|
|
3e5297 |
+ fi
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ [ -d /run/systemd/system ] || exit 0
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ users=$(systemctl list-units 'user@*' --legend=no | sed -n -r 's/.*user@([0-9]+).service.*/\1/p')
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ if [[ "$command" =~ reload ]]; then
|
|
|
3e5297 |
+ for user in $users; do
|
|
|
3e5297 |
+ SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
|
|
|
3e5297 |
+ systemctl --user -M "$user@" daemon-reload &
|
|
|
3e5297 |
+ done
|
|
|
3e5297 |
+ wait
|
|
|
3e5297 |
+ fi
|
|
|
3e5297 |
+
|
|
|
3e5297 |
+ if [[ "$command" =~ restart ]]; then
|
|
|
3e5297 |
+ for user in $users; do
|
|
|
3e5297 |
+ SYSTEMD_BUS_TIMEOUT={{UPDATE_HELPER_USER_TIMEOUT}} \
|
|
|
3e5297 |
+ systemctl --user -M "$user@" reload-or-restart --marked &
|
|
|
3e5297 |
+ done
|
|
|
3e5297 |
+ wait
|
|
|
3e5297 |
+ fi
|
|
|
3e5297 |
+ ;;
|
|
|
3e5297 |
+
|
|
|
3e5297 |
*)
|
|
|
3e5297 |
echo "Unknown verb '$command'"
|
|
|
3e5297 |
exit 3
|
|
|
3e5297 |
diff --git a/src/rpm/triggers.systemd.in b/src/rpm/triggers.systemd.in
|
|
|
3e5297 |
index d29cc33dfd..8aeb2049c1 100644
|
|
|
3e5297 |
--- a/src/rpm/triggers.systemd.in
|
|
|
3e5297 |
+++ b/src/rpm/triggers.systemd.in
|
|
|
3e5297 |
@@ -20,6 +20,14 @@ elseif pid > 0 then
|
|
|
3e5297 |
posix.wait(pid)
|
|
|
3e5297 |
end
|
|
|
3e5297 |
|
|
|
3e5297 |
+%transfiletriggerin -P 900899 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
|
|
3e5297 |
+pid = posix.fork()
|
|
|
3e5297 |
+if pid == 0 then
|
|
|
3e5297 |
+ assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload-restart"))
|
|
|
3e5297 |
+elseif pid > 0 then
|
|
|
3e5297 |
+ posix.wait(pid)
|
|
|
3e5297 |
+end
|
|
|
3e5297 |
+
|
|
|
3e5297 |
%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
|
|
3e5297 |
-- On removal, we need to run daemon-reload after any units have been
|
|
|
3e5297 |
-- removed.
|
|
|
3e5297 |
@@ -33,8 +41,17 @@ elseif pid > 0 then
|
|
|
3e5297 |
posix.wait(pid)
|
|
|
3e5297 |
end
|
|
|
3e5297 |
|
|
|
3e5297 |
+%transfiletriggerpostun -P 1000100 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
|
|
3e5297 |
+-- Execute daemon-reload in user managers.
|
|
|
3e5297 |
+pid = posix.fork()
|
|
|
3e5297 |
+if pid == 0 then
|
|
|
3e5297 |
+ assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-reload"))
|
|
|
3e5297 |
+elseif pid > 0 then
|
|
|
3e5297 |
+ posix.wait(pid)
|
|
|
3e5297 |
+end
|
|
|
3e5297 |
+
|
|
|
3e5297 |
%transfiletriggerpostun -P 10000 -p <lua> -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
|
|
3e5297 |
--- We restart remaining services that should be restarted here.
|
|
|
3e5297 |
+-- We restart remaining system services that should be restarted here.
|
|
|
3e5297 |
pid = posix.fork()
|
|
|
3e5297 |
if pid == 0 then
|
|
|
3e5297 |
assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "system-restart"))
|
|
|
3e5297 |
@@ -42,6 +59,15 @@ elseif pid > 0 then
|
|
|
3e5297 |
posix.wait(pid)
|
|
|
3e5297 |
end
|
|
|
3e5297 |
|
|
|
3e5297 |
+%transfiletriggerpostun -P 9999 -p <lua> -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
|
|
3e5297 |
+-- We restart remaining user services that should be restarted here.
|
|
|
3e5297 |
+pid = posix.fork()
|
|
|
3e5297 |
+if pid == 0 then
|
|
|
3e5297 |
+ assert(posix.exec("{{SYSTEMD_UPDATE_HELPER_PATH}}", "user-restart"))
|
|
|
3e5297 |
+elseif pid > 0 then
|
|
|
3e5297 |
+ posix.wait(pid)
|
|
|
3e5297 |
+end
|
|
|
3e5297 |
+
|
|
|
3e5297 |
%transfiletriggerin -P 100700 -p <lua> -- {{SYSUSERS_DIR}}
|
|
|
3e5297 |
-- This script will process files installed in {{SYSUSERS_DIR}} to create
|
|
|
3e5297 |
-- specified users automatically. The priority is set such that it
|
|
|
3e5297 |
diff --git a/src/rpm/triggers.systemd.sh.in b/src/rpm/triggers.systemd.sh.in
|
|
|
3e5297 |
index 83cd7617f8..694cd94e8d 100644
|
|
|
3e5297 |
--- a/src/rpm/triggers.systemd.sh.in
|
|
|
3e5297 |
+++ b/src/rpm/triggers.systemd.sh.in
|
|
|
3e5297 |
@@ -16,6 +16,9 @@
|
|
|
3e5297 |
# so sometimes we will reload needlessly.
|
|
|
3e5297 |
{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload-restart || :
|
|
|
3e5297 |
|
|
|
3e5297 |
+%transfiletriggerin -P 900899 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
|
|
3e5297 |
+{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload-restart || :
|
|
|
3e5297 |
+
|
|
|
3e5297 |
%transfiletriggerpostun -P 1000100 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
|
|
3e5297 |
# On removal, we need to run daemon-reload after any units have been
|
|
|
3e5297 |
# removed.
|
|
|
3e5297 |
@@ -24,10 +27,18 @@
|
|
|
3e5297 |
# executed.
|
|
|
3e5297 |
{{SYSTEMD_UPDATE_HELPER_PATH}} system-reload || :
|
|
|
3e5297 |
|
|
|
3e5297 |
+%transfiletriggerpostun -P 1000099 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
|
|
3e5297 |
+# Execute daemon-reload in user managers.
|
|
|
3e5297 |
+{{SYSTEMD_UPDATE_HELPER_PATH}} user-reload || :
|
|
|
3e5297 |
+
|
|
|
3e5297 |
%transfiletriggerpostun -P 10000 -- {{SYSTEM_DATA_UNIT_DIR}} /etc/systemd/system
|
|
|
3e5297 |
-# We restart remaining services that should be restarted here.
|
|
|
3e5297 |
+# We restart remaining system services that should be restarted here.
|
|
|
3e5297 |
{{SYSTEMD_UPDATE_HELPER_PATH}} system-restart || :
|
|
|
3e5297 |
|
|
|
3e5297 |
+%transfiletriggerpostun -P 9999 -- {{USER_DATA_UNIT_DIR}} /etc/systemd/user
|
|
|
3e5297 |
+# We restart remaining user services that should be restarted here.
|
|
|
3e5297 |
+{{SYSTEMD_UPDATE_HELPER_PATH}} user-restart || :
|
|
|
3e5297 |
+
|
|
|
3e5297 |
%transfiletriggerin -P 1000700 -- {{SYSUSERS_DIR}}
|
|
|
3e5297 |
# This script will process files installed in {{SYSUSERS_DIR}} to create
|
|
|
3e5297 |
# specified users automatically. The priority is set such that it
|
|
|
3e5297 |
--
|
|
|
3e5297 |
2.31.1
|
|
|
3e5297 |
|