]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
src: die during shutdown with everything else wip/fix-remount-failure
authorRay Strode <rstrode@redhat.com>
Fri, 17 Jul 2020 20:06:44 +0000 (16:06 -0400)
committerRay Strode <rstrode@redhat.com>
Mon, 20 Jul 2020 19:48:31 +0000 (15:48 -0400)
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

12 files changed:
configure.ac
scripts/plymouth-populate-initrd.in
src/Makefile.am
src/main.c
src/plugins/renderers/drm/Makefile.am
src/plugins/renderers/drm/plugin.c
src/plymouthd-drm-escrow.c [new file with mode: 0644]
systemd-units/Makefile.am
systemd-units/plymouth-halt.service.in
systemd-units/plymouth-poweroff.service.in
systemd-units/plymouth-reboot.service.in
systemd-units/plymouth-switch-root-initramfs.service.in [new file with mode: 0644]

index 1a2314bb61a30751ebe5f7d65fc937a53f614b60..d2d62287407cb7073db1f9ba57109516411b132d 100644 (file)
@@ -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
index 616ecc4eedb9c22d26d25548e590ba8553218812..4e35186b5311bbf71b78af46818ee28ee03dd175 100755 (executable)
@@ -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
index 95ed019265ec77a114a1b7242d6290193f2a34d8..78f3f788207d9f0e285e6d3f1018286259d17ada 100644 (file)
@@ -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
index 8848ad0dc8f8852591093becf38db9475bdb549e..8372f2f895306f4de1f7ce660e8ef8efde05f12a 100644 (file)
@@ -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);
 
index 271b17f437726a2796cb9a1e6a228b1f914e9a1c..22a819b63ebb43cf5b9e38fd2d2c0d439060c8d4 100644 (file)
@@ -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
index 4dbf8da8dca952cb626850185b06680da190aa38..38bae3678bf1ca8b4b1d96e0ee51a46c556dcec3 100644 (file)
@@ -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 (file)
index 0000000..9097db9
--- /dev/null
@@ -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;
+}
index b1d843b6a0864794eb4e6058f76765eb3c7a8783..bfede1728e1d3613369d1a5562ef5cdd0466c875 100644 (file)
@@ -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        \
index cb87c1f4f7994b546218b93c7f9fbb2064b55dbe..00f7eed9fceb1408e5f3ede0ad25c81a95fae906 100644 (file)
@@ -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
index cf05e47f3355b724382acbe861fb05ff0b3dafec..a1f78eb4294572baed02db867fe29277c3d59f11 100644 (file)
@@ -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
index 3624550dcf13b471130da6dd3f29ca816b61f7c7..8fff576f313631e1ce3f0c51667c5ee7e53e076c 100644 (file)
@@ -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 (file)
index 0000000..cb20459
--- /dev/null
@@ -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