Blame SOURCES/0001-src-die-during-shutdown-with-everything-else.patch

e382aa
From f55051678452647e035853ee94a89cb54ea2aa4a Mon Sep 17 00:00:00 2001
e382aa
From: Ray Strode <rstrode@redhat.com>
e382aa
Date: Fri, 17 Jul 2020 16:06:44 -0400
e382aa
Subject: [PATCH] src: die during shutdown with everything else
e382aa
e382aa
plymouthd currently avoids getting killed at shutdown.  This causes
e382aa
filesystems to fail to remount read-only in some cases.
e382aa
e382aa
This commit changes things up so that plymouthd dies with everyone else,
e382aa
but spawns a process to hold open the drm device that can keep the splash
e382aa
up until the very end.
e382aa
e382aa
In order to keep this process alive until the very end, it gets run
e382aa
from within the initramfs (if available).  This requires adding service
e382aa
files to jump back into the initramfs at shutdown
e382aa
---
e382aa
 configure.ac                                  |  1 +
e382aa
 scripts/plymouth-populate-initrd.in           |  2 +
e382aa
 src/Makefile.am                               |  7 +++
e382aa
 src/main.c                                    | 11 +++-
e382aa
 src/plugins/renderers/drm/Makefile.am         |  3 +-
e382aa
 src/plugins/renderers/drm/plugin.c            | 62 +++++++++++++++++++
e382aa
 src/plymouthd-drm-escrow.c                    | 18 ++++++
e382aa
 systemd-units/Makefile.am                     | 28 ++++++---
e382aa
 systemd-units/plymouth-halt.service.in        |  1 +
e382aa
 systemd-units/plymouth-poweroff.service.in    |  1 +
e382aa
 systemd-units/plymouth-reboot.service.in      |  1 +
e382aa
 .../plymouth-switch-root-initramfs.service.in | 12 ++++
e382aa
 12 files changed, 134 insertions(+), 13 deletions(-)
e382aa
 create mode 100644 src/plymouthd-drm-escrow.c
e382aa
 create mode 100644 systemd-units/plymouth-switch-root-initramfs.service.in
e382aa
e382aa
diff --git a/configure.ac b/configure.ac
e382aa
index 970e19f..1dc8cdb 100644
e382aa
--- a/configure.ac
e382aa
+++ b/configure.ac
e382aa
@@ -319,36 +319,37 @@ AC_CONFIG_FILES([Makefile po/Makefile.in
e382aa
            src/plugins/controls/label/Makefile
e382aa
            src/Makefile
e382aa
            src/client/ply-boot-client.pc
e382aa
            src/client/Makefile
e382aa
            src/upstart-bridge/Makefile
e382aa
            themes/Makefile
e382aa
            themes/spinfinity/Makefile
e382aa
            themes/fade-in/Makefile
e382aa
            themes/tribar/Makefile
e382aa
            themes/text/Makefile
e382aa
            themes/details/Makefile
e382aa
            themes/solar/Makefile
e382aa
            themes/glow/Makefile
e382aa
            themes/spinner/Makefile
e382aa
            themes/script/Makefile
e382aa
            themes/bgrt/Makefile
e382aa
            images/Makefile
e382aa
 	   scripts/plymouth-generate-initrd
e382aa
 	   scripts/plymouth-populate-initrd
e382aa
 	   scripts/plymouth-set-default-theme
e382aa
            scripts/Makefile
e382aa
            systemd-units/plymouth-halt.service
e382aa
            systemd-units/plymouth-kexec.service
e382aa
            systemd-units/plymouth-poweroff.service
e382aa
            systemd-units/plymouth-quit.service
e382aa
            systemd-units/plymouth-quit-wait.service
e382aa
            systemd-units/plymouth-read-write.service
e382aa
            systemd-units/plymouth-reboot.service
e382aa
            systemd-units/plymouth-start.service
e382aa
            systemd-units/plymouth-switch-root.service
e382aa
+           systemd-units/plymouth-switch-root-initramfs.service
e382aa
            systemd-units/systemd-ask-password-plymouth.path
e382aa
            systemd-units/systemd-ask-password-plymouth.service
e382aa
            systemd-units/Makefile
e382aa
            docs/Makefile
e382aa
 ])
e382aa
 AC_OUTPUT
e382aa
diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in
e382aa
index 60fd063..535a896 100755
e382aa
--- a/scripts/plymouth-populate-initrd.in
e382aa
+++ b/scripts/plymouth-populate-initrd.in
e382aa
@@ -1,54 +1,55 @@
e382aa
 #!/bin/bash
e382aa
 #
e382aa
 # inst bits ruthlessly and viciously stolen from dracut
e382aa
 
e382aa
 [ -z "$DESTDIR" ] || exit 0
e382aa
 
e382aa
 # For running on a (cross-compiled) sysroot, the following
e382aa
 # settings are needed:
e382aa
 # PLYMOUTH_SYSROOT - the sysroot directory
e382aa
 # PLYMOUTH_LDD - an optional ldd command that works on foreign binaries
e382aa
 # PLYMOUTH_LDD_PATH - optional PATH ldd is run with
e382aa
 
e382aa
 [ -z "$PLYMOUTH_LDD" ] && PLYMOUTH_LDD="ldd"
e382aa
 [ -z "$PLYMOUTH_LDD_PATH" ] && PLYMOUTH_LDD_PATH="$PATH"
e382aa
 [ -z "$PLYMOUTH_LIBEXECDIR" ] && PLYMOUTH_LIBEXECDIR="@PLYMOUTH_LIBEXECDIR@"
e382aa
 [ -z "$PLYMOUTH_DATADIR" ] && PLYMOUTH_DATADIR="@PLYMOUTH_DATADIR@"
e382aa
 [ -z "$PLYMOUTH_PLUGIN_PATH" ] && PLYMOUTH_PLUGIN_PATH="$(plymouth --get-splash-plugin-path)"
e382aa
 [ -z "$PLYMOUTH_LOGO_FILE" ] && PLYMOUTH_LOGO_FILE="@PLYMOUTH_LOGO_FILE@"
e382aa
 [ -n "$PLYMOUTH_THEME_NAME" ] && THEME_OVERRIDE=1
e382aa
 [ -z "$PLYMOUTH_THEME_NAME" ] && PLYMOUTH_THEME_NAME=$(plymouth-set-default-theme)
e382aa
 [ -z "$PLYMOUTH_CONFDIR" ] && PLYMOUTH_CONFDIR="@PLYMOUTH_CONF_DIR@"
e382aa
 [ -z "$PLYMOUTH_POLICYDIR" ] && PLYMOUTH_POLICYDIR="@PLYMOUTH_POLICY_DIR@"
e382aa
 [ -z "$PLYMOUTH_DAEMON_PATH" ] && PLYMOUTH_DAEMON_PATH="@PLYMOUTH_DAEMON_DIR@/plymouthd"
e382aa
 [ -z "$PLYMOUTH_CLIENT_PATH" ] && PLYMOUTH_CLIENT_PATH="@PLYMOUTH_CLIENT_DIR@/plymouth"
e382aa
+[ -z "$PLYMOUTH_DRM_ESCROW_PATH" ] && PLYMOUTH_DRM_ESCROW_PATH="@PLYMOUTH_LIBEXECDIR@/plymouth/plymouth-drm-escrow"
e382aa
 [ -z "$SYSTEMD_UNIT_DIR" ] && SYSTEMD_UNIT_DIR="@SYSTEMD_UNIT_DIR@"
e382aa
 [ -z "$SUPPORTED_LANGUAGES" ] && SUPPORTED_LANGUAGES="pt fr de it ru es en zh ja ko zh as bn gu hi kn ml mr or pa ta te"
e382aa
 
e382aa
 # Generic substring function.  If $2 is in $1, return 0.
e382aa
 strstr() { [ "${1#*$2*}" != "$1" ]; }
e382aa
 
e382aa
 ddebug() {
e382aa
     [ "$verbose" = "true" ] && echo "$@"
e382aa
 }
e382aa
 
e382aa
 # normalize_path <path>
e382aa
 # Prints the normalized path, where it removes any duplicated
e382aa
 # and trailing slashes.
e382aa
 # Example:
e382aa
 # $ normalize_path ///test/test//
e382aa
 # /test/test
e382aa
 normalize_path() {
e382aa
     shopt -q -s extglob
e382aa
     set -- "${1//+(\/)//}"
e382aa
     shopt -q -u extglob
e382aa
     echo "${1%/}"
e382aa
 }
e382aa
 
e382aa
 # convert_abs_rel <from> <to>
e382aa
 # Prints the relative path, when creating a symlink to <to> from <from>.
e382aa
 # Example:
e382aa
 # $ convert_abs_rel /usr/bin/test /bin/test-2
e382aa
 # ../../bin/test-2
e382aa
 # $ ln -s $(convert_abs_rel /usr/bin/test /bin/test-2) /usr/bin/test
e382aa
 convert_abs_rel() {
e382aa
@@ -390,60 +391,61 @@ verbose=false
e382aa
 INITRDDIR=""
e382aa
 while [ $# -gt 0 ]; do
e382aa
     case $1 in
e382aa
         --verbose|-v)
e382aa
             verbose=true
e382aa
             ;;
e382aa
         --targetdir|-t)
e382aa
             shift
e382aa
             INITRDDIR="$1"
e382aa
             ;;
e382aa
         --help|-h)
e382aa
             usage normal
e382aa
             ;;
e382aa
         *)
e382aa
             usage error
e382aa
             break
e382aa
             ;;
e382aa
     esac
e382aa
     shift
e382aa
 done
e382aa
 
e382aa
 [ -z "$INITRDDIR" ] && usage error
e382aa
 
e382aa
 ddebug "Running with PLYMOUTH_SYSROOT=$PLYMOUTH_SYSROOT"
e382aa
 ddebug "Running with PLYMOUTH_LDD=$PLYMOUTH_LDD"
e382aa
 ddebug "Running with PLYMOUTH_LDD_PATH=$PLYMOUTH_LDD_PATH"
e382aa
 
e382aa
 mkdir -p ${INITRDDIR}${PLYMOUTH_DATADIR}/plymouth/themes
e382aa
 inst ${PLYMOUTH_DAEMON_PATH} $INITRDDIR
e382aa
 inst ${PLYMOUTH_CLIENT_PATH} $INITRDDIR
e382aa
+inst ${PLYMOUTH_DRM_ESCROW_PATH} $INITRDDIR
e382aa
 inst ${PLYMOUTH_DATADIR}/plymouth/themes/text/text.plymouth $INITRDDIR
e382aa
 inst ${PLYMOUTH_PLUGIN_PATH}/text.so $INITRDDIR
e382aa
 inst ${PLYMOUTH_DATADIR}/plymouth/themes/details/details.plymouth $INITRDDIR
e382aa
 inst ${PLYMOUTH_PLUGIN_PATH}/details.so $INITRDDIR
e382aa
 inst ${PLYMOUTH_LOGO_FILE} $INITRDDIR
e382aa
 inst @RELEASE_FILE@ $INITRDDIR
e382aa
 inst ${PLYMOUTH_POLICYDIR}/plymouthd.defaults $INITRDDIR
e382aa
 inst ${PLYMOUTH_CONFDIR}/plymouthd.conf $INITRDDIR
e382aa
 
e382aa
 if [ -z "$PLYMOUTH_THEME_NAME" ]; then
e382aa
     echo "No default plymouth plugin is set" >&2
e382aa
     exit 1
e382aa
 fi
e382aa
 
e382aa
 if [ $THEME_OVERRIDE ]; then
e382aa
     conf=$INITRDDIR/${PLYMOUTH_CONFDIR}/plymouthd.conf
e382aa
     echo "modifying plymouthd.conf: Theme=$PLYMOUTH_THEME_NAME" >&2
e382aa
     # make sure the section and key exist so we can modify them
e382aa
     grep -q "^ *\[Daemon\]" $conf || echo "[Daemon]" >> $conf
e382aa
     grep -q "^ *Theme *=" $conf || echo "Theme=fade-in" >> $conf
e382aa
     sed -i "s/^ *Theme *=.*/# theme modified by plymouth-populate-initrd\nTheme=$PLYMOUTH_THEME_NAME/" $conf
e382aa
 fi
e382aa
 
e382aa
 PLYMOUTH_MODULE_NAME=$(grep "ModuleName *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ModuleName *= *//')
e382aa
 PLYMOUTH_THEME_DIR="${PLYMOUTH_DATADIR}/plymouth/themes/${PLYMOUTH_THEME_NAME}"
e382aa
 PLYMOUTH_IMAGE_DIR=$(grep "ImageDir *= *" ${PLYMOUTH_SYSROOT}${PLYMOUTH_THEME_DIR}/${PLYMOUTH_THEME_NAME}.plymouth | sed 's/ImageDir *= *//')
e382aa
 
e382aa
 if [ ! -f ${PLYMOUTH_SYSROOT}${PLYMOUTH_PLUGIN_PATH}/${PLYMOUTH_MODULE_NAME}.so ]; then
e382aa
     echo "The default plymouth plugin (${PLYMOUTH_MODULE_NAME}) doesn't exist" >&2
e382aa
     exit 1
e382aa
diff --git a/src/Makefile.am b/src/Makefile.am
e382aa
index 95ed019..78f3f78 100644
e382aa
--- a/src/Makefile.am
e382aa
+++ b/src/Makefile.am
e382aa
@@ -1,52 +1,59 @@
e382aa
 SUBDIRS = libply libply-splash-core libply-splash-graphics . plugins client
e382aa
 if ENABLE_UPSTART_MONITORING
e382aa
 SUBDIRS += upstart-bridge
e382aa
 endif
e382aa
 AM_CPPFLAGS = -I$(top_srcdir)                                                 \
e382aa
            -I$(srcdir)/libply                                                 \
e382aa
            -I$(srcdir)/libply-splash-core                                     \
e382aa
            -I$(srcdir)                                                        \
e382aa
+           -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\"         \
e382aa
            -DPLYMOUTH_LOG_DIRECTORY=\"$(localstatedir)/log\"                  \
e382aa
            -DPLYMOUTH_SPOOL_DIRECTORY=\"$(localstatedir)/spool/plymouth\"     \
e382aa
            -DPLYMOUTH_TIME_DIRECTORY=\"$(localstatedir)/lib/plymouth/\"       \
e382aa
            -DPLYMOUTH_LOGO_FILE=\"$(logofile)\"
e382aa
 
e382aa
 plymouthdbindir = $(plymouthdaemondir)
e382aa
 plymouthdbin_PROGRAMS = plymouthd
e382aa
 
e382aa
 plymouthd_CFLAGS = $(PLYMOUTH_CFLAGS)                                         \
e382aa
 		   -rdynamic                                                  \
e382aa
 		   -DPLYMOUTH_PLUGIN_PATH=\"$(PLYMOUTH_PLUGIN_PATH)\"         \
e382aa
 		   -DPLYMOUTH_THEME_PATH=\"$(PLYMOUTH_THEME_PATH)/\"          \
e382aa
 		   -DPLYMOUTH_POLICY_DIR=\"$(PLYMOUTH_POLICY_DIR)/\"          \
e382aa
 		   -DPLYMOUTH_RUNTIME_DIR=\"$(PLYMOUTH_RUNTIME_DIR)\"         \
e382aa
 		   -DPLYMOUTH_CONF_DIR=\"$(PLYMOUTH_CONF_DIR)/\"              \
e382aa
 		   -DPLYMOUTH_RUNTIME_THEME_PATH=\"$(PLYMOUTH_RUNTIME_THEME_PATH)/\"
e382aa
 plymouthd_LDADD = $(PLYMOUTH_LIBS) libply/libply.la libply-splash-core/libply-splash-core.la
e382aa
 plymouthd_SOURCES =                                                            \
e382aa
                    ply-boot-protocol.h                                        \
e382aa
                    ply-boot-server.h                                          \
e382aa
                    ply-boot-server.c                                          \
e382aa
                    plugins/splash/details/plugin.c                  \
e382aa
                    main.c
e382aa
 
e382aa
+escrowdir = $(libexecdir)/plymouth
e382aa
+escrow_PROGRAMS = plymouthd-drm-escrow
e382aa
+
e382aa
+plymouthd_drm_escrow_LDFLAGS = -all-static
e382aa
+plymouthd_drm_escrow_SOURCES = plymouthd-drm-escrow.c
e382aa
+
e382aa
 plymouthdrundir = $(localstatedir)/run/plymouth
e382aa
 plymouthdspooldir = $(localstatedir)/spool/plymouth
e382aa
 plymouthdtimedir = $(localstatedir)/lib/plymouth
e382aa
 
e382aa
 pkgconfigdir = $(libdir)/pkgconfig
e382aa
 pkgconfig_DATA = ply-splash-core.pc ply-splash-graphics.pc
e382aa
 
e382aa
 plymouthd_defaultsdir = $(PLYMOUTH_POLICY_DIR)
e382aa
 dist_plymouthd_defaults_DATA = plymouthd.defaults
e382aa
 
e382aa
 plymouthd_confdir = $(PLYMOUTH_CONF_DIR)
e382aa
 dist_plymouthd_conf_DATA = plymouthd.conf
e382aa
 
e382aa
 install-data-hook:
e382aa
 	-mkdir -p $(DESTDIR)$(plymouthdrundir)
e382aa
 	-mkdir -p $(DESTDIR)$(plymouthdspooldir)
e382aa
 	-mkdir -p $(DESTDIR)$(plymouthdtimedir)
e382aa
 
e382aa
 EXTRA_DIST = ply-splash-core.pc.in ply-splash-graphics.pc.in
e382aa
 MAINTAINERCLEANFILES = Makefile.in
e382aa
diff --git a/src/main.c b/src/main.c
e382aa
index 8848ad0..8372f2f 100644
e382aa
--- a/src/main.c
e382aa
+++ b/src/main.c
e382aa
@@ -2181,65 +2181,70 @@ main (int    argc,
e382aa
 
e382aa
                 if (daemon_handle == NULL) {
e382aa
                         ply_error ("plymouthd: cannot daemonize: %m");
e382aa
                         return EX_UNAVAILABLE;
e382aa
                 }
e382aa
         }
e382aa
 
e382aa
         if (debug)
e382aa
                 debug_buffer = ply_buffer_new ();
e382aa
 
e382aa
         signal (SIGABRT, on_crash);
e382aa
         signal (SIGSEGV, on_crash);
e382aa
 
e382aa
         /* before do anything we need to make sure we have a working
e382aa
          * environment.
e382aa
          */
e382aa
         if (!initialize_environment (&state)) {
e382aa
                 if (errno == 0) {
e382aa
                         if (daemon_handle != NULL)
e382aa
                                 ply_detach_daemon (daemon_handle, 0);
e382aa
                         return 0;
e382aa
                 }
e382aa
 
e382aa
                 ply_error ("plymouthd: could not setup basic operating environment: %m");
e382aa
                 if (daemon_handle != NULL)
e382aa
                         ply_detach_daemon (daemon_handle, EX_OSERR);
e382aa
                 return EX_OSERR;
e382aa
         }
e382aa
 
e382aa
         /* Make the first byte in argv be '@' so that we can survive systemd's killing
e382aa
-         * spree when going from initrd to /, and so we stay alive all the way until
e382aa
-         * the power is killed at shutdown.
e382aa
+         * spree when going from initrd to /
e382aa
          * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
e382aa
+         *
e382aa
+         * If the system is shutting down, we let systemd slay us because otherwise we
e382aa
+         * may prevent the root fs from getting remounted read-only.
e382aa
          */
e382aa
-        argv[0][0] = '@';
e382aa
+        if (state.mode != PLY_BOOT_SPLASH_MODE_SHUTDOWN &&
e382aa
+	    state.mode != PLY_BOOT_SPLASH_MODE_REBOOT) {
e382aa
+                argv[0][0] = '@';
e382aa
+        }
e382aa
 
e382aa
         state.boot_server = start_boot_server (&state);
e382aa
 
e382aa
         if (state.boot_server == NULL) {
e382aa
                 ply_trace ("plymouthd is already running");
e382aa
 
e382aa
                 if (daemon_handle != NULL)
e382aa
                         ply_detach_daemon (daemon_handle, EX_OK);
e382aa
                 return EX_OK;
e382aa
         }
e382aa
 
e382aa
         state.boot_buffer = ply_buffer_new ();
e382aa
 
e382aa
         if (attach_to_session) {
e382aa
                 state.should_be_attached = attach_to_session;
e382aa
                 if (!attach_to_running_session (&state)) {
e382aa
                         ply_trace ("could not redirect console session: %m");
e382aa
                         if (!no_daemon)
e382aa
                                 ply_detach_daemon (daemon_handle, EX_UNAVAILABLE);
e382aa
                         return EX_UNAVAILABLE;
e382aa
                 }
e382aa
         }
e382aa
 
e382aa
         state.progress = ply_progress_new ();
e382aa
         state.splash_delay = NAN;
e382aa
         state.device_timeout = NAN;
e382aa
 
e382aa
         ply_progress_load_cache (state.progress,
e382aa
                                  get_cache_file_for_mode (state.mode));
e382aa
 
e382aa
diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am
e382aa
index 271b17f..22a819b 100644
e382aa
--- a/src/plugins/renderers/drm/Makefile.am
e382aa
+++ b/src/plugins/renderers/drm/Makefile.am
e382aa
@@ -1,23 +1,24 @@
e382aa
 if ENABLE_DRM_RENDERER
e382aa
 AM_CPPFLAGS = -I$(top_srcdir)                                                 \
e382aa
            -I$(srcdir)/../../../libply                                        \
e382aa
            -I$(srcdir)/../../../libply-splash-core                            \
e382aa
            -I$(srcdir)/../../..                                               \
e382aa
            -I$(srcdir)/../..                                                  \
e382aa
            -I$(srcdir)/..                                                     \
e382aa
-           -I$(srcdir)
e382aa
+           -I$(srcdir)                                                        \
e382aa
+           -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\"
e382aa
 
e382aa
 plugindir = $(libdir)/plymouth/renderers
e382aa
 plugin_LTLIBRARIES = drm.la
e382aa
 
e382aa
 drm_la_CFLAGS = $(PLYMOUTH_CFLAGS) $(DRM_CFLAGS)
e382aa
 
e382aa
 drm_la_LDFLAGS = -module -avoid-version -export-dynamic
e382aa
 drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS)                                  \
e382aa
                          ../../../libply/libply.la                            \
e382aa
                          ../../../libply-splash-core/libply-splash-core.la
e382aa
 drm_la_SOURCES = $(srcdir)/plugin.c
e382aa
 
e382aa
 endif
e382aa
 
e382aa
 MAINTAINERCLEANFILES = Makefile.in
e382aa
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
e382aa
index 4dbf8da..38bae36 100644
e382aa
--- a/src/plugins/renderers/drm/plugin.c
e382aa
+++ b/src/plugins/renderers/drm/plugin.c
e382aa
@@ -131,73 +131,79 @@ typedef struct
e382aa
         bool connected;
e382aa
         bool uses_hw_rotation;
e382aa
 } ply_output_t;
e382aa
 
e382aa
 struct _ply_renderer_backend
e382aa
 {
e382aa
         ply_event_loop_t                *loop;
e382aa
         ply_terminal_t                  *terminal;
e382aa
 
e382aa
         int                              device_fd;
e382aa
         char                            *device_name;
e382aa
         drmModeRes                      *resources;
e382aa
 
e382aa
         ply_renderer_input_source_t      input_source;
e382aa
         ply_list_t                      *heads;
e382aa
         ply_hashtable_t                 *heads_by_controller_id;
e382aa
 
e382aa
         ply_hashtable_t                 *output_buffers;
e382aa
 
e382aa
         ply_output_t                    *outputs;
e382aa
         int                              outputs_len;
e382aa
         int                              connected_count;
e382aa
 
e382aa
         int32_t                          dither_red;
e382aa
         int32_t                          dither_green;
e382aa
         int32_t                          dither_blue;
e382aa
 
e382aa
         uint32_t                         is_active : 1;
e382aa
         uint32_t        requires_explicit_flushing : 1;
e382aa
         uint32_t                use_preferred_mode : 1;
e382aa
+        uint32_t          watching_for_termination : 1;
e382aa
 
e382aa
         int                              panel_width;
e382aa
         int                              panel_height;
e382aa
         ply_pixel_buffer_rotation_t      panel_rotation;
e382aa
         int                              panel_scale;
e382aa
 };
e382aa
 
e382aa
 ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
e382aa
 static bool open_input_source (ply_renderer_backend_t      *backend,
e382aa
                                ply_renderer_input_source_t *input_source);
e382aa
 static void flush_head (ply_renderer_backend_t *backend,
e382aa
                         ply_renderer_head_t    *head);
e382aa
 
e382aa
+static void close_device (ply_renderer_backend_t *backend);
e382aa
+
e382aa
+static void watch_for_termination (ply_renderer_backend_t *backend);
e382aa
+static void stop_watching_for_termination (ply_renderer_backend_t *backend);
e382aa
+
e382aa
 /* A small helper to determine if we should try to keep the current mode
e382aa
  * or pick the best mode ourselves, we keep the current mode only if the
e382aa
  * user specified a specific mode using video= on the commandline.
e382aa
  */
e382aa
 static bool
e382aa
 should_use_preferred_mode (void)
e382aa
 {
e382aa
         bool use_preferred_mode = true;
e382aa
 
e382aa
         if (ply_kernel_command_line_get_string_after_prefix ("video="))
e382aa
                 use_preferred_mode = false;
e382aa
 
e382aa
         ply_trace ("should_use_preferred_mode: %d", use_preferred_mode);
e382aa
 
e382aa
         return use_preferred_mode;
e382aa
 }
e382aa
 
e382aa
 static bool
e382aa
 ply_renderer_buffer_map (ply_renderer_backend_t *backend,
e382aa
                          ply_renderer_buffer_t  *buffer)
e382aa
 {
e382aa
         struct drm_mode_map_dumb map_dumb_buffer_request;
e382aa
         void *map_address;
e382aa
 
e382aa
         if (buffer->map_address != MAP_FAILED) {
e382aa
                 buffer->map_count++;
e382aa
                 return true;
e382aa
         }
e382aa
 
e382aa
         memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb));
e382aa
@@ -918,158 +924,214 @@ static void
e382aa
 destroy_backend (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         ply_trace ("destroying renderer backend for device %s", backend->device_name);
e382aa
         free_heads (backend);
e382aa
 
e382aa
         free (backend->device_name);
e382aa
         ply_hashtable_free (backend->output_buffers);
e382aa
         ply_hashtable_free (backend->heads_by_controller_id);
e382aa
 
e382aa
         free (backend->outputs);
e382aa
         free (backend);
e382aa
 }
e382aa
 
e382aa
 static void
e382aa
 activate (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         ply_renderer_head_t *head;
e382aa
         ply_list_node_t *node;
e382aa
 
e382aa
         ply_trace ("taking master and scanning out");
e382aa
         backend->is_active = true;
e382aa
 
e382aa
         drmSetMaster (backend->device_fd);
e382aa
         node = ply_list_get_first_node (backend->heads);
e382aa
         while (node != NULL) {
e382aa
                 head = (ply_renderer_head_t *) ply_list_node_get_data (node);
e382aa
                 /* Flush out any pending drawing to the buffer */
e382aa
                 flush_head (backend, head);
e382aa
                 node = ply_list_get_next_node (backend->heads, node);
e382aa
         }
e382aa
+
e382aa
+        watch_for_termination (backend);
e382aa
 }
e382aa
 
e382aa
 static void
e382aa
 deactivate (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         ply_trace ("dropping master");
e382aa
         drmDropMaster (backend->device_fd);
e382aa
         backend->is_active = false;
e382aa
+
e382aa
+        stop_watching_for_termination (backend);
e382aa
 }
e382aa
 
e382aa
 static void
e382aa
 on_active_vt_changed (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         if (ply_terminal_is_active (backend->terminal)) {
e382aa
                 ply_trace ("activating on vt change");
e382aa
                 activate (backend);
e382aa
         } else {
e382aa
                 ply_trace ("deactivating on vt change");
e382aa
                 deactivate (backend);
e382aa
         }
e382aa
 }
e382aa
 
e382aa
 static bool
e382aa
 load_driver (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         int device_fd;
e382aa
 
e382aa
         ply_trace ("Opening '%s'", backend->device_name);
e382aa
         device_fd = open (backend->device_name, O_RDWR);
e382aa
 
e382aa
         if (device_fd < 0) {
e382aa
                 ply_trace ("open failed: %m");
e382aa
                 return false;
e382aa
         }
e382aa
 
e382aa
         backend->device_fd = device_fd;
e382aa
 
e382aa
         drmDropMaster (device_fd);
e382aa
 
e382aa
         return true;
e382aa
 }
e382aa
 
e382aa
 static void
e382aa
 unload_backend (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         if (backend == NULL)
e382aa
                 return;
e382aa
 
e382aa
         ply_trace ("unloading backend");
e382aa
 
e382aa
         if (backend->device_fd >= 0) {
e382aa
                 drmClose (backend->device_fd);
e382aa
                 backend->device_fd = -1;
e382aa
         }
e382aa
 
e382aa
         destroy_backend (backend);
e382aa
         backend = NULL;
e382aa
 
e382aa
 }
e382aa
 
e382aa
+static void
e382aa
+on_term_signal (ply_renderer_backend_t *backend)
e382aa
+{
e382aa
+        pid_t pid;
e382aa
+
e382aa
+        ply_trace ("got SIGTERM, launching drm escrow to protect splash, and dying");
e382aa
+
e382aa
+        pid = fork();
e382aa
+
e382aa
+        if (pid == 0) {
e382aa
+                const char *argv[] = { PLYMOUTH_DRM_ESCROW_DIRECTORY "/plymouthd-drm-escrow", NULL };
e382aa
+
e382aa
+                dup (backend->device_fd);
e382aa
+                execve (argv[0], (char * const *) argv, NULL);
e382aa
+
e382aa
+		ply_trace ("could not launch drm escrow process: %m");
e382aa
+
e382aa
+                _exit (1);
e382aa
+        }
e382aa
+
e382aa
+
e382aa
+	close_device (backend);
e382aa
+
e382aa
+        exit (0);
e382aa
+}
e382aa
+
e382aa
+static void
e382aa
+watch_for_termination (ply_renderer_backend_t *backend)
e382aa
+{
e382aa
+        if (backend->watching_for_termination)
e382aa
+                return;
e382aa
+
e382aa
+	ply_trace ("watching for termination signal");
e382aa
+        ply_event_loop_watch_signal (backend->loop, SIGTERM, (ply_event_handler_t) on_term_signal, backend);
e382aa
+        backend->watching_for_termination = true;
e382aa
+}
e382aa
+
e382aa
+static void
e382aa
+stop_watching_for_termination (ply_renderer_backend_t *backend)
e382aa
+{
e382aa
+        if (!backend->watching_for_termination)
e382aa
+                return;
e382aa
+
e382aa
+	ply_trace ("stopping watching for termination signal");
e382aa
+        ply_event_loop_stop_watching_signal (backend->loop, SIGTERM);
e382aa
+        backend->watching_for_termination = false;
e382aa
+}
e382aa
+
e382aa
 static bool
e382aa
 open_device (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         assert (backend != NULL);
e382aa
         assert (backend->device_name != NULL);
e382aa
 
e382aa
         if (!load_driver (backend))
e382aa
                 return false;
e382aa
 
e382aa
         if (backend->terminal == NULL)
e382aa
                 return true;
e382aa
 
e382aa
         if (!ply_terminal_open (backend->terminal)) {
e382aa
                 ply_trace ("could not open terminal: %m");
e382aa
                 return false;
e382aa
         }
e382aa
 
e382aa
         if (!ply_terminal_is_vt (backend->terminal)) {
e382aa
                 ply_trace ("terminal is not a VT");
e382aa
                 ply_terminal_close (backend->terminal);
e382aa
                 return false;
e382aa
         }
e382aa
 
e382aa
         ply_terminal_watch_for_active_vt_change (backend->terminal,
e382aa
                                                  (ply_terminal_active_vt_changed_handler_t)
e382aa
                                                  on_active_vt_changed,
e382aa
                                                  backend);
e382aa
 
e382aa
+        watch_for_termination (backend);
e382aa
+
e382aa
         return true;
e382aa
 }
e382aa
 
e382aa
 static void
e382aa
 close_device (ply_renderer_backend_t *backend)
e382aa
 {
e382aa
         ply_trace ("closing device");
e382aa
 
e382aa
         free_heads (backend);
e382aa
 
e382aa
+        stop_watching_for_termination (backend);
e382aa
+
e382aa
         if (backend->terminal != NULL) {
e382aa
                 ply_terminal_stop_watching_for_active_vt_change (backend->terminal,
e382aa
                                                                  (ply_terminal_active_vt_changed_handler_t)
e382aa
                                                                  on_active_vt_changed,
e382aa
                                                                  backend);
e382aa
         }
e382aa
 
e382aa
         unload_backend (backend);
e382aa
 }
e382aa
 
e382aa
 static void
e382aa
 output_get_controller_info (ply_renderer_backend_t *backend,
e382aa
                             drmModeConnector       *connector,
e382aa
                             ply_output_t           *output)
e382aa
 {
e382aa
         int i;
e382aa
         drmModeEncoder *encoder;
e382aa
 
e382aa
         assert (backend != NULL);
e382aa
 
e382aa
         output->possible_controllers = 0xffffffff;
e382aa
 
e382aa
         for (i = 0; i < connector->count_encoders; i++) {
e382aa
                 encoder = drmModeGetEncoder (backend->device_fd,
e382aa
                                              connector->encoders[i]);
e382aa
 
e382aa
                 if (encoder == NULL)
e382aa
                         continue;
e382aa
 
e382aa
                 if (encoder->encoder_id == connector->encoder_id && encoder->crtc_id) {
e382aa
diff --git a/src/plymouthd-drm-escrow.c b/src/plymouthd-drm-escrow.c
e382aa
new file mode 100644
e382aa
index 0000000..9097db9
e382aa
--- /dev/null
e382aa
+++ b/src/plymouthd-drm-escrow.c
e382aa
@@ -0,0 +1,18 @@
e382aa
+#include <signal.h>
e382aa
+#include <unistd.h>
e382aa
+
e382aa
+int
e382aa
+main(int argc, char **argv)
e382aa
+{
e382aa
+	signal (SIGTERM, SIG_IGN);
e382aa
+
e382aa
+        /* Make the first byte in argv be '@' so that we can survive systemd's killing
e382aa
+         * spree until the power is killed at shutdown.
e382aa
+         * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
e382aa
+         */
e382aa
+        argv[0][0] = '@';
e382aa
+
e382aa
+        while (pause());
e382aa
+
e382aa
+        return 0;
e382aa
+}
e382aa
diff --git a/systemd-units/Makefile.am b/systemd-units/Makefile.am
e382aa
index b1d843b..bfede17 100644
e382aa
--- a/systemd-units/Makefile.am
e382aa
+++ b/systemd-units/Makefile.am
e382aa
@@ -1,78 +1,88 @@
e382aa
 systemd_unit_templates =                                                     \
e382aa
         plymouth-switch-root.service.in                                      \
e382aa
+        plymouth-switch-root-initramfs.service.in                            \
e382aa
         plymouth-start.service.in                                            \
e382aa
         plymouth-read-write.service.in                                       \
e382aa
         plymouth-quit.service.in                                             \
e382aa
         plymouth-quit-wait.service.in                                        \
e382aa
         plymouth-reboot.service.in                                           \
e382aa
         plymouth-kexec.service.in                                            \
e382aa
         plymouth-poweroff.service.in                                         \
e382aa
         plymouth-halt.service.in                                             \
e382aa
         systemd-ask-password-plymouth.path.in                                \
e382aa
         systemd-ask-password-plymouth.service.in
e382aa
 
e382aa
 if ENABLE_SYSTEMD_INTEGRATION
e382aa
 systemdunitdir=$(SYSTEMD_UNIT_DIR)
e382aa
 systemdunit_DATA = $(systemd_unit_templates:.in=)
e382aa
 
e382aa
 install-data-hook:
e382aa
 	$(MKDIR_P) -m 0755                                                   \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/initrd-switch-root.target.wants\
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants           \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants        \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants            \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants             \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants          \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/initrd-switch-root.target.wants && \
e382aa
 		rm -f plymouth-start.service plymouth-switch-root.service && \
e382aa
 		$(LN_S) ../plymouth-start.service &&                         \
e382aa
 		$(LN_S) ../plymouth-switch-root.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants &&            \
e382aa
 		rm -f plymouth-start.service plymouth-read-write.service &&  \
e382aa
 		$(LN_S) ../plymouth-start.service &&                         \
e382aa
 		$(LN_S) ../plymouth-read-write.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants &&         \
e382aa
 		rm -f plymouth-quit.service plymouth-quit-wait.service &&    \
e382aa
 		$(LN_S) ../plymouth-quit.service &&                          \
e382aa
 		$(LN_S) ../plymouth-quit-wait.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants &&             \
e382aa
-		rm -f plymouth-reboot.service &&                             \
e382aa
-		$(LN_S) ../plymouth-reboot.service)
e382aa
+		rm -f plymouth-reboot.service                                \
e382aa
+		      plymouth-switch-root-initramfs.service &&              \
e382aa
+		$(LN_S) ../plymouth-reboot.service &&                        \
e382aa
+		$(LN_S) ../plymouth-switch-root-initramfs.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants &&              \
e382aa
 		rm -f plymouth-kexec.service &&                              \
e382aa
 		$(LN_S) ../plymouth-kexec.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants &&           \
e382aa
-		rm -f plymouth-poweroff.service &&                           \
e382aa
-		$(LN_S) ../plymouth-poweroff.service)
e382aa
+		rm -f plymouth-poweroff.service                              \
e382aa
+		      plymouth-switch-root-initramfs.service &&              \
e382aa
+		$(LN_S) ../plymouth-poweroff.service &&                      \
e382aa
+		$(LN_S) ../plymouth-switch-root-initramfs.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants &&               \
e382aa
-		rm -f plymouth-halt.service &&                               \
e382aa
-		$(LN_S) ../plymouth-halt.service)
e382aa
+		rm -f plymouth-halt.service                                  \
e382aa
+		      plymouth-switch-root-initramfs.service &&              \
e382aa
+		$(LN_S) ../plymouth-halt.service &&                          \
e382aa
+		$(LN_S) ../plymouth-switch-root-initramfs.service)
e382aa
 
e382aa
 uninstall-hook:
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/initrd-switch-root.target.wants && \
e382aa
 		rm -f plymouth-start.service plymouth-switch-root.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants &&            \
e382aa
 		rm -f plymouth-start.service plymouth-read-write.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants &&         \
e382aa
 		rm -f plymouth-quit.service plymouth-quit-wait.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants &&             \
e382aa
-		rm -f plymouth-reboot.service)
e382aa
+		rm -f plymouth-reboot.service                                \
e382aa
+		      plymouth-switch-root-initramfs.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants &&              \
e382aa
 		rm -f plymouth-kexec.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants &&           \
e382aa
-		rm -f plymouth-poweroff.service)
e382aa
+		rm -f plymouth-poweroff.service                              \
e382aa
+		      plymouth-switch-root-initramfs.service)
e382aa
 	(cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants &&               \
e382aa
-		rm -f plymouth-halt.service)
e382aa
+		rm -f plymouth-halt.service                                  \
e382aa
+		      plymouth-switch-root-initramfs.service)
e382aa
 	rmdir --ignore-fail-on-non-empty                                     \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants           \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants        \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/reboot.target.wants            \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/kexec.target.wants             \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants          \
e382aa
 		$(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants
e382aa
 
e382aa
 endif
e382aa
 
e382aa
 EXTRA_DIST = $(systemd_unit_templates) $(systemdunit_DATA)
e382aa
 DISTCLEANFILES=$(systemdunit_DATA)
e382aa
diff --git a/systemd-units/plymouth-halt.service.in b/systemd-units/plymouth-halt.service.in
e382aa
index cb87c1f..00f7eed 100644
e382aa
--- a/systemd-units/plymouth-halt.service.in
e382aa
+++ b/systemd-units/plymouth-halt.service.in
e382aa
@@ -1,13 +1,14 @@
e382aa
 [Unit]
e382aa
 Description=Show Plymouth Halt Screen
e382aa
 After=getty@tty1.service display-manager.service plymouth-start.service
e382aa
 Before=systemd-halt.service
e382aa
 DefaultDependencies=no
e382aa
 ConditionKernelCommandLine=!plymouth.enable=0
e382aa
 ConditionVirtualization=!container
e382aa
 
e382aa
 [Service]
e382aa
 ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=shutdown --attach-to-session
e382aa
 ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
e382aa
+KillMode=none
e382aa
 Type=forking
e382aa
 RemainAfterExit=yes
e382aa
diff --git a/systemd-units/plymouth-poweroff.service.in b/systemd-units/plymouth-poweroff.service.in
e382aa
index cf05e47..a1f78eb 100644
e382aa
--- a/systemd-units/plymouth-poweroff.service.in
e382aa
+++ b/systemd-units/plymouth-poweroff.service.in
e382aa
@@ -1,13 +1,14 @@
e382aa
 [Unit]
e382aa
 Description=Show Plymouth Power Off Screen
e382aa
 After=getty@tty1.service display-manager.service plymouth-start.service
e382aa
 Before=systemd-poweroff.service
e382aa
 DefaultDependencies=no
e382aa
 ConditionKernelCommandLine=!plymouth.enable=0
e382aa
 ConditionVirtualization=!container
e382aa
 
e382aa
 [Service]
e382aa
 ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=shutdown --attach-to-session
e382aa
 ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
e382aa
+KillMode=none
e382aa
 Type=forking
e382aa
 RemainAfterExit=yes
e382aa
diff --git a/systemd-units/plymouth-reboot.service.in b/systemd-units/plymouth-reboot.service.in
e382aa
index 3624550..8fff576 100644
e382aa
--- a/systemd-units/plymouth-reboot.service.in
e382aa
+++ b/systemd-units/plymouth-reboot.service.in
e382aa
@@ -1,13 +1,14 @@
e382aa
 [Unit]
e382aa
 Description=Show Plymouth Reboot Screen
e382aa
 After=getty@tty1.service display-manager.service plymouth-start.service
e382aa
 Before=systemd-reboot.service
e382aa
 DefaultDependencies=no
e382aa
 ConditionKernelCommandLine=!plymouth.enable=0
e382aa
 ConditionVirtualization=!container
e382aa
 
e382aa
 [Service]
e382aa
 ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=reboot --attach-to-session
e382aa
 ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
e382aa
+KillMode=none
e382aa
 Type=forking
e382aa
 RemainAfterExit=yes
e382aa
diff --git a/systemd-units/plymouth-switch-root-initramfs.service.in b/systemd-units/plymouth-switch-root-initramfs.service.in
e382aa
new file mode 100644
e382aa
index 0000000..cb20459
e382aa
--- /dev/null
e382aa
+++ b/systemd-units/plymouth-switch-root-initramfs.service.in
e382aa
@@ -0,0 +1,12 @@
e382aa
+[Unit]
e382aa
+Description=Tell Plymouth To Jump To initramfs
e382aa
+DefaultDependencies=no
e382aa
+After=plymouth-halt.service plymouth-reboot.service plymouth-poweroff.service dracut-shutdown.service
e382aa
+ConditionPathExists=/run/initramfs/bin/sh
e382aa
+
e382aa
+[Service]
e382aa
+Type=oneshot
e382aa
+RemainAfterExit=yes
e382aa
+ExecStart=-@PLYMOUTH_CLIENT_DIR@/plymouth update-root-fs --new-root-dir=/run/initramfs
e382aa
+Type=oneshot
e382aa
+RemainAfterExit=yes
e382aa
-- 
e382aa
2.26.0
e382aa