summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2020-07-17 16:06:44 -0400
committerRay Strode <rstrode@redhat.com>2020-07-20 15:48:31 -0400
commit00df82fea8f7e6c6e441e30166191fdd682e328f (patch)
tree812644bdcdda86aa011bae6fea11575ecb1f9a59
parentab986a95824e2a701a77dd9405d411a5c022c613 (diff)
src: die during shutdown with everything elsewip/fix-remount-failure
plymouthd currently avoids getting killed at shutdown. This causes filesystems to fail to remount read-only in some cases. This commit changes things up so that plymouthd dies with everyone else, but spawns a process to hold open the drm device that can keep the splash up until the very end. In order to keep this process alive until the very end, it gets run from within the initramfs (if available). This requires adding service files to jump back into the initramfs at shutdown
-rw-r--r--configure.ac1
-rwxr-xr-xscripts/plymouth-populate-initrd.in2
-rw-r--r--src/Makefile.am7
-rw-r--r--src/main.c11
-rw-r--r--src/plugins/renderers/drm/Makefile.am3
-rw-r--r--src/plugins/renderers/drm/plugin.c62
-rw-r--r--src/plymouthd-drm-escrow.c18
-rw-r--r--systemd-units/Makefile.am28
-rw-r--r--systemd-units/plymouth-halt.service.in1
-rw-r--r--systemd-units/plymouth-poweroff.service.in1
-rw-r--r--systemd-units/plymouth-reboot.service.in1
-rw-r--r--systemd-units/plymouth-switch-root-initramfs.service.in12
12 files changed, 134 insertions, 13 deletions
diff --git a/configure.ac b/configure.ac
index 1a2314bb..d2d62287 100644
--- a/configure.ac
+++ b/configure.ac
@@ -341,6 +341,7 @@ AC_CONFIG_FILES([Makefile po/Makefile.in
systemd-units/plymouth-reboot.service
systemd-units/plymouth-start.service
systemd-units/plymouth-switch-root.service
+ systemd-units/plymouth-switch-root-initramfs.service
systemd-units/systemd-ask-password-plymouth.path
systemd-units/systemd-ask-password-plymouth.service
systemd-units/Makefile
diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in
index 616ecc4e..4e35186b 100755
--- a/scripts/plymouth-populate-initrd.in
+++ b/scripts/plymouth-populate-initrd.in
@@ -22,6 +22,7 @@
[ -z "$PLYMOUTH_POLICYDIR" ] && PLYMOUTH_POLICYDIR="@PLYMOUTH_POLICY_DIR@"
[ -z "$PLYMOUTH_DAEMON_PATH" ] && PLYMOUTH_DAEMON_PATH="@PLYMOUTH_DAEMON_DIR@/plymouthd"
[ -z "$PLYMOUTH_CLIENT_PATH" ] && PLYMOUTH_CLIENT_PATH="@PLYMOUTH_CLIENT_DIR@/plymouth"
+[ -z "$PLYMOUTH_DRM_ESCROW_PATH" ] && PLYMOUTH_DRM_ESCROW_PATH="@PLYMOUTH_LIBEXECDIR@/plymouth/plymouth-drm-escrow"
[ -z "$SYSTEMD_UNIT_DIR" ] && SYSTEMD_UNIT_DIR="@SYSTEMD_UNIT_DIR@"
# Generic substring function. If $2 is in $1, return 0.
@@ -416,6 +417,7 @@ ddebug "Running with PLYMOUTH_LDD_PATH=$PLYMOUTH_LDD_PATH"
mkdir -p ${INITRDDIR}${PLYMOUTH_DATADIR}/plymouth/themes
inst ${PLYMOUTH_DAEMON_PATH} $INITRDDIR
inst ${PLYMOUTH_CLIENT_PATH} $INITRDDIR
+inst ${PLYMOUTH_DRM_ESCROW_PATH} $INITRDDIR
inst ${PLYMOUTH_DATADIR}/plymouth/themes/text/text.plymouth $INITRDDIR
inst ${PLYMOUTH_PLUGIN_PATH}/text.so $INITRDDIR
inst ${PLYMOUTH_DATADIR}/plymouth/themes/details/details.plymouth $INITRDDIR
diff --git a/src/Makefile.am b/src/Makefile.am
index 95ed0192..78f3f788 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = -I$(top_srcdir) \
-I$(srcdir)/libply \
-I$(srcdir)/libply-splash-core \
-I$(srcdir) \
+ -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\" \
-DPLYMOUTH_LOG_DIRECTORY=\"$(localstatedir)/log\" \
-DPLYMOUTH_SPOOL_DIRECTORY=\"$(localstatedir)/spool/plymouth\" \
-DPLYMOUTH_TIME_DIRECTORY=\"$(localstatedir)/lib/plymouth/\" \
@@ -30,6 +31,12 @@ plymouthd_SOURCES = \
plugins/splash/details/plugin.c \
main.c
+escrowdir = $(libexecdir)/plymouth
+escrow_PROGRAMS = plymouthd-drm-escrow
+
+plymouthd_drm_escrow_LDFLAGS = -all-static
+plymouthd_drm_escrow_SOURCES = plymouthd-drm-escrow.c
+
plymouthdrundir = $(localstatedir)/run/plymouth
plymouthdspooldir = $(localstatedir)/spool/plymouth
plymouthdtimedir = $(localstatedir)/lib/plymouth
diff --git a/src/main.c b/src/main.c
index 8848ad0d..8372f2f8 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2208,11 +2208,16 @@ main (int argc,
}
/* Make the first byte in argv be '@' so that we can survive systemd's killing
- * spree when going from initrd to /, and so we stay alive all the way until
- * the power is killed at shutdown.
+ * spree when going from initrd to /
* http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
+ *
+ * If the system is shutting down, we let systemd slay us because otherwise we
+ * may prevent the root fs from getting remounted read-only.
*/
- argv[0][0] = '@';
+ if (state.mode != PLY_BOOT_SPLASH_MODE_SHUTDOWN &&
+ state.mode != PLY_BOOT_SPLASH_MODE_REBOOT) {
+ argv[0][0] = '@';
+ }
state.boot_server = start_boot_server (&state);
diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am
index 271b17f4..22a819b6 100644
--- a/src/plugins/renderers/drm/Makefile.am
+++ b/src/plugins/renderers/drm/Makefile.am
@@ -5,7 +5,8 @@ AM_CPPFLAGS = -I$(top_srcdir) \
-I$(srcdir)/../../.. \
-I$(srcdir)/../.. \
-I$(srcdir)/.. \
- -I$(srcdir)
+ -I$(srcdir) \
+ -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\"
plugindir = $(libdir)/plymouth/renderers
plugin_LTLIBRARIES = drm.la
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
index 4dbf8da8..38bae367 100644
--- a/src/plugins/renderers/drm/plugin.c
+++ b/src/plugins/renderers/drm/plugin.c
@@ -158,6 +158,7 @@ struct _ply_renderer_backend
uint32_t is_active : 1;
uint32_t requires_explicit_flushing : 1;
uint32_t use_preferred_mode : 1;
+ uint32_t watching_for_termination : 1;
int panel_width;
int panel_height;
@@ -171,6 +172,11 @@ static bool open_input_source (ply_renderer_backend_t *backend,
static void flush_head (ply_renderer_backend_t *backend,
ply_renderer_head_t *head);
+static void close_device (ply_renderer_backend_t *backend);
+
+static void watch_for_termination (ply_renderer_backend_t *backend);
+static void stop_watching_for_termination (ply_renderer_backend_t *backend);
+
/* A small helper to determine if we should try to keep the current mode
* or pick the best mode ourselves, we keep the current mode only if the
* user specified a specific mode using video= on the commandline.
@@ -945,6 +951,8 @@ activate (ply_renderer_backend_t *backend)
flush_head (backend, head);
node = ply_list_get_next_node (backend->heads, node);
}
+
+ watch_for_termination (backend);
}
static void
@@ -953,6 +961,8 @@ deactivate (ply_renderer_backend_t *backend)
ply_trace ("dropping master");
drmDropMaster (backend->device_fd);
backend->is_active = false;
+
+ stop_watching_for_termination (backend);
}
static void
@@ -1005,6 +1015,54 @@ unload_backend (ply_renderer_backend_t *backend)
}
+static void
+on_term_signal (ply_renderer_backend_t *backend)
+{
+ pid_t pid;
+
+ ply_trace ("got SIGTERM, launching drm escrow to protect splash, and dying");
+
+ pid = fork();
+
+ if (pid == 0) {
+ const char *argv[] = { PLYMOUTH_DRM_ESCROW_DIRECTORY "/plymouthd-drm-escrow", NULL };
+
+ dup (backend->device_fd);
+ execve (argv[0], (char * const *) argv, NULL);
+
+ ply_trace ("could not launch drm escrow process: %m");
+
+ _exit (1);
+ }
+
+
+ close_device (backend);
+
+ exit (0);
+}
+
+static void
+watch_for_termination (ply_renderer_backend_t *backend)
+{
+ if (backend->watching_for_termination)
+ return;
+
+ ply_trace ("watching for termination signal");
+ ply_event_loop_watch_signal (backend->loop, SIGTERM, (ply_event_handler_t) on_term_signal, backend);
+ backend->watching_for_termination = true;
+}
+
+static void
+stop_watching_for_termination (ply_renderer_backend_t *backend)
+{
+ if (!backend->watching_for_termination)
+ return;
+
+ ply_trace ("stopping watching for termination signal");
+ ply_event_loop_stop_watching_signal (backend->loop, SIGTERM);
+ backend->watching_for_termination = false;
+}
+
static bool
open_device (ply_renderer_backend_t *backend)
{
@@ -1033,6 +1091,8 @@ open_device (ply_renderer_backend_t *backend)
on_active_vt_changed,
backend);
+ watch_for_termination (backend);
+
return true;
}
@@ -1043,6 +1103,8 @@ close_device (ply_renderer_backend_t *backend)
free_heads (backend);
+ stop_watching_for_termination (backend);
+
if (backend->terminal != NULL) {
ply_terminal_stop_watching_for_active_vt_change (backend->terminal,
(ply_terminal_active_vt_changed_handler_t)
diff --git a/src/plymouthd-drm-escrow.c b/src/plymouthd-drm-escrow.c
new file mode 100644
index 00000000..9097db91
--- /dev/null
+++ b/src/plymouthd-drm-escrow.c
@@ -0,0 +1,18 @@
+#include <signal.h>
+#include <unistd.h>
+
+int
+main(int argc, char **argv)
+{
+ signal (SIGTERM, SIG_IGN);
+
+ /* Make the first byte in argv be '@' so that we can survive systemd's killing
+ * spree until the power is killed at shutdown.
+ * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
+ */
+ argv[0][0] = '@';
+
+ while (pause());
+
+ return 0;
+}
diff --git a/systemd-units/Makefile.am b/systemd-units/Makefile.am
index b1d843b6..bfede172 100644
--- a/systemd-units/Makefile.am
+++ b/systemd-units/Makefile.am
@@ -1,5 +1,6 @@
systemd_unit_templates = \
plymouth-switch-root.service.in \
+ plymouth-switch-root-initramfs.service.in \
plymouth-start.service.in \
plymouth-read-write.service.in \
plymouth-quit.service.in \
@@ -37,17 +38,23 @@ install-data-hook:
$(LN_S) ../plymouth-quit.service && \
$(LN_S) ../plymouth-quit-wait.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants && \
- rm -f plymouth-reboot.service && \
- $(LN_S) ../plymouth-reboot.service)
+ rm -f plymouth-reboot.service \
+ plymouth-switch-root-initramfs.service && \
+ $(LN_S) ../plymouth-reboot.service && \
+ $(LN_S) ../plymouth-switch-root-initramfs.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants && \
rm -f plymouth-kexec.service && \
$(LN_S) ../plymouth-kexec.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants && \
- rm -f plymouth-poweroff.service && \
- $(LN_S) ../plymouth-poweroff.service)
+ rm -f plymouth-poweroff.service \
+ plymouth-switch-root-initramfs.service && \
+ $(LN_S) ../plymouth-poweroff.service && \
+ $(LN_S) ../plymouth-switch-root-initramf.services)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants && \
- rm -f plymouth-halt.service && \
- $(LN_S) ../plymouth-halt.service)
+ rm -f plymouth-halt.service \
+ plymouth-switch-root-initramfs.service && \
+ $(LN_S) ../plymouth-halt.service && \
+ $(LN_S) ../plymouth-switch-root-initramfs.service)
uninstall-hook:
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/initrd-switch-root.target.wants && \
@@ -57,13 +64,16 @@ uninstall-hook:
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants && \
rm -f plymouth-quit.service plymouth-quit-wait.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants && \
- rm -f plymouth-reboot.service)
+ rm -f plymouth-reboot.service \
+ plymouth-switch-root-initramfs.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants && \
rm -f plymouth-kexec.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants && \
- rm -f plymouth-poweroff.service)
+ rm -f plymouth-poweroff.service \
+ plymouth-switch-root-initramfs.service)
(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants && \
- rm -f plymouth-halt.service)
+ rm -f plymouth-halt.service \
+ plymouth-switch-root-initramfs.service)
rmdir --ignore-fail-on-non-empty \
$(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants \
$(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants \
diff --git a/systemd-units/plymouth-halt.service.in b/systemd-units/plymouth-halt.service.in
index cb87c1f4..00f7eed9 100644
--- a/systemd-units/plymouth-halt.service.in
+++ b/systemd-units/plymouth-halt.service.in
@@ -9,5 +9,6 @@ ConditionVirtualization=!container
[Service]
ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=shutdown --attach-to-session
ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
+KillMode=none
Type=forking
RemainAfterExit=yes
diff --git a/systemd-units/plymouth-poweroff.service.in b/systemd-units/plymouth-poweroff.service.in
index cf05e47f..a1f78eb4 100644
--- a/systemd-units/plymouth-poweroff.service.in
+++ b/systemd-units/plymouth-poweroff.service.in
@@ -9,5 +9,6 @@ ConditionVirtualization=!container
[Service]
ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=shutdown --attach-to-session
ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
+KillMode=none
Type=forking
RemainAfterExit=yes
diff --git a/systemd-units/plymouth-reboot.service.in b/systemd-units/plymouth-reboot.service.in
index 3624550d..8fff576f 100644
--- a/systemd-units/plymouth-reboot.service.in
+++ b/systemd-units/plymouth-reboot.service.in
@@ -9,5 +9,6 @@ ConditionVirtualization=!container
[Service]
ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=reboot --attach-to-session
ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
+KillMode=none
Type=forking
RemainAfterExit=yes
diff --git a/systemd-units/plymouth-switch-root-initramfs.service.in b/systemd-units/plymouth-switch-root-initramfs.service.in
new file mode 100644
index 00000000..cb20459d
--- /dev/null
+++ b/systemd-units/plymouth-switch-root-initramfs.service.in
@@ -0,0 +1,12 @@
+[Unit]
+Description=Tell Plymouth To Jump To initramfs
+DefaultDependencies=no
+After=plymouth-halt.service plymouth-reboot.service plymouth-poweroff.service dracut-shutdown.service
+ConditionPathExists=/run/initramfs/bin/sh
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=-@PLYMOUTH_CLIENT_DIR@/plymouth update-root-fs --new-root-dir=/run/initramfs
+Type=oneshot
+RemainAfterExit=yes