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

647dcb
From 43b4f60da9b468ffb3e782d91b9c01c845a339af Mon Sep 17 00:00:00 2001
647dcb
From: Ray Strode <rstrode@redhat.com>
647dcb
Date: Fri, 17 Jul 2020 16:06:44 -0400
647dcb
Subject: [PATCH] src: die during shutdown with everything else
647dcb
647dcb
plymouthd currently avoids getting killed at shutdown.  This causes
647dcb
filesystems to fail to remount read-only in some cases.
647dcb
647dcb
This commit changes things up so that plymouthd dies with everyone else,
647dcb
but spawns a process to hold open the drm device that can keep the splash
647dcb
up until the very end.
647dcb
---
647dcb
 src/Makefile.am                            |  7 +++
647dcb
 src/main.c                                 | 11 ++--
647dcb
 src/plugins/renderers/drm/Makefile.am      |  3 +-
647dcb
 src/plugins/renderers/drm/plugin.c         | 62 ++++++++++++++++++++++
647dcb
 src/plymouthd-drm-escrow.c                 | 18 +++++++
647dcb
 systemd-units/plymouth-halt.service.in     |  1 +
647dcb
 systemd-units/plymouth-poweroff.service.in |  1 +
647dcb
 systemd-units/plymouth-reboot.service.in   |  1 +
647dcb
 8 files changed, 100 insertions(+), 4 deletions(-)
647dcb
 create mode 100644 src/plymouthd-drm-escrow.c
647dcb
647dcb
diff --git a/src/Makefile.am b/src/Makefile.am
647dcb
index 95ed019..78f3f78 100644
647dcb
--- a/src/Makefile.am
647dcb
+++ b/src/Makefile.am
647dcb
@@ -1,52 +1,59 @@
647dcb
 SUBDIRS = libply libply-splash-core libply-splash-graphics . plugins client
647dcb
 if ENABLE_UPSTART_MONITORING
647dcb
 SUBDIRS += upstart-bridge
647dcb
 endif
647dcb
 AM_CPPFLAGS = -I$(top_srcdir)                                                 \
647dcb
            -I$(srcdir)/libply                                                 \
647dcb
            -I$(srcdir)/libply-splash-core                                     \
647dcb
            -I$(srcdir)                                                        \
647dcb
+           -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\"         \
647dcb
            -DPLYMOUTH_LOG_DIRECTORY=\"$(localstatedir)/log\"                  \
647dcb
            -DPLYMOUTH_SPOOL_DIRECTORY=\"$(localstatedir)/spool/plymouth\"     \
647dcb
            -DPLYMOUTH_TIME_DIRECTORY=\"$(localstatedir)/lib/plymouth/\"       \
647dcb
            -DPLYMOUTH_LOGO_FILE=\"$(logofile)\"
647dcb
 
647dcb
 plymouthdbindir = $(plymouthdaemondir)
647dcb
 plymouthdbin_PROGRAMS = plymouthd
647dcb
 
647dcb
 plymouthd_CFLAGS = $(PLYMOUTH_CFLAGS)                                         \
647dcb
 		   -rdynamic                                                  \
647dcb
 		   -DPLYMOUTH_PLUGIN_PATH=\"$(PLYMOUTH_PLUGIN_PATH)\"         \
647dcb
 		   -DPLYMOUTH_THEME_PATH=\"$(PLYMOUTH_THEME_PATH)/\"          \
647dcb
 		   -DPLYMOUTH_POLICY_DIR=\"$(PLYMOUTH_POLICY_DIR)/\"          \
647dcb
 		   -DPLYMOUTH_RUNTIME_DIR=\"$(PLYMOUTH_RUNTIME_DIR)\"         \
647dcb
 		   -DPLYMOUTH_CONF_DIR=\"$(PLYMOUTH_CONF_DIR)/\"              \
647dcb
 		   -DPLYMOUTH_RUNTIME_THEME_PATH=\"$(PLYMOUTH_RUNTIME_THEME_PATH)/\"
647dcb
 plymouthd_LDADD = $(PLYMOUTH_LIBS) libply/libply.la libply-splash-core/libply-splash-core.la
647dcb
 plymouthd_SOURCES =                                                            \
647dcb
                    ply-boot-protocol.h                                        \
647dcb
                    ply-boot-server.h                                          \
647dcb
                    ply-boot-server.c                                          \
647dcb
                    plugins/splash/details/plugin.c                  \
647dcb
                    main.c
647dcb
 
647dcb
+escrowdir = $(libexecdir)/plymouth
647dcb
+escrow_PROGRAMS = plymouthd-drm-escrow
647dcb
+
647dcb
+plymouthd_drm_escrow_LDFLAGS = -all-static
647dcb
+plymouthd_drm_escrow_SOURCES = plymouthd-drm-escrow.c
647dcb
+
647dcb
 plymouthdrundir = $(localstatedir)/run/plymouth
647dcb
 plymouthdspooldir = $(localstatedir)/spool/plymouth
647dcb
 plymouthdtimedir = $(localstatedir)/lib/plymouth
647dcb
 
647dcb
 pkgconfigdir = $(libdir)/pkgconfig
647dcb
 pkgconfig_DATA = ply-splash-core.pc ply-splash-graphics.pc
647dcb
 
647dcb
 plymouthd_defaultsdir = $(PLYMOUTH_POLICY_DIR)
647dcb
 dist_plymouthd_defaults_DATA = plymouthd.defaults
647dcb
 
647dcb
 plymouthd_confdir = $(PLYMOUTH_CONF_DIR)
647dcb
 dist_plymouthd_conf_DATA = plymouthd.conf
647dcb
 
647dcb
 install-data-hook:
647dcb
 	-mkdir -p $(DESTDIR)$(plymouthdrundir)
647dcb
 	-mkdir -p $(DESTDIR)$(plymouthdspooldir)
647dcb
 	-mkdir -p $(DESTDIR)$(plymouthdtimedir)
647dcb
 
647dcb
 EXTRA_DIST = ply-splash-core.pc.in ply-splash-graphics.pc.in
647dcb
 MAINTAINERCLEANFILES = Makefile.in
647dcb
diff --git a/src/main.c b/src/main.c
647dcb
index 8848ad0..8372f2f 100644
647dcb
--- a/src/main.c
647dcb
+++ b/src/main.c
647dcb
@@ -2181,65 +2181,70 @@ main (int    argc,
647dcb
 
647dcb
                 if (daemon_handle == NULL) {
647dcb
                         ply_error ("plymouthd: cannot daemonize: %m");
647dcb
                         return EX_UNAVAILABLE;
647dcb
                 }
647dcb
         }
647dcb
 
647dcb
         if (debug)
647dcb
                 debug_buffer = ply_buffer_new ();
647dcb
 
647dcb
         signal (SIGABRT, on_crash);
647dcb
         signal (SIGSEGV, on_crash);
647dcb
 
647dcb
         /* before do anything we need to make sure we have a working
647dcb
          * environment.
647dcb
          */
647dcb
         if (!initialize_environment (&state)) {
647dcb
                 if (errno == 0) {
647dcb
                         if (daemon_handle != NULL)
647dcb
                                 ply_detach_daemon (daemon_handle, 0);
647dcb
                         return 0;
647dcb
                 }
647dcb
 
647dcb
                 ply_error ("plymouthd: could not setup basic operating environment: %m");
647dcb
                 if (daemon_handle != NULL)
647dcb
                         ply_detach_daemon (daemon_handle, EX_OSERR);
647dcb
                 return EX_OSERR;
647dcb
         }
647dcb
 
647dcb
         /* Make the first byte in argv be '@' so that we can survive systemd's killing
647dcb
-         * spree when going from initrd to /, and so we stay alive all the way until
647dcb
-         * the power is killed at shutdown.
647dcb
+         * spree when going from initrd to /
647dcb
          * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
647dcb
+         *
647dcb
+         * If the system is shutting down, we let systemd slay us because otherwise we
647dcb
+         * may prevent the root fs from getting remounted read-only.
647dcb
          */
647dcb
-        argv[0][0] = '@';
647dcb
+        if (state.mode != PLY_BOOT_SPLASH_MODE_SHUTDOWN &&
647dcb
+	    state.mode != PLY_BOOT_SPLASH_MODE_REBOOT) {
647dcb
+                argv[0][0] = '@';
647dcb
+        }
647dcb
 
647dcb
         state.boot_server = start_boot_server (&state);
647dcb
 
647dcb
         if (state.boot_server == NULL) {
647dcb
                 ply_trace ("plymouthd is already running");
647dcb
 
647dcb
                 if (daemon_handle != NULL)
647dcb
                         ply_detach_daemon (daemon_handle, EX_OK);
647dcb
                 return EX_OK;
647dcb
         }
647dcb
 
647dcb
         state.boot_buffer = ply_buffer_new ();
647dcb
 
647dcb
         if (attach_to_session) {
647dcb
                 state.should_be_attached = attach_to_session;
647dcb
                 if (!attach_to_running_session (&state)) {
647dcb
                         ply_trace ("could not redirect console session: %m");
647dcb
                         if (!no_daemon)
647dcb
                                 ply_detach_daemon (daemon_handle, EX_UNAVAILABLE);
647dcb
                         return EX_UNAVAILABLE;
647dcb
                 }
647dcb
         }
647dcb
 
647dcb
         state.progress = ply_progress_new ();
647dcb
         state.splash_delay = NAN;
647dcb
         state.device_timeout = NAN;
647dcb
 
647dcb
         ply_progress_load_cache (state.progress,
647dcb
                                  get_cache_file_for_mode (state.mode));
647dcb
 
647dcb
diff --git a/src/plugins/renderers/drm/Makefile.am b/src/plugins/renderers/drm/Makefile.am
647dcb
index 271b17f..22a819b 100644
647dcb
--- a/src/plugins/renderers/drm/Makefile.am
647dcb
+++ b/src/plugins/renderers/drm/Makefile.am
647dcb
@@ -1,23 +1,24 @@
647dcb
 if ENABLE_DRM_RENDERER
647dcb
 AM_CPPFLAGS = -I$(top_srcdir)                                                 \
647dcb
            -I$(srcdir)/../../../libply                                        \
647dcb
            -I$(srcdir)/../../../libply-splash-core                            \
647dcb
            -I$(srcdir)/../../..                                               \
647dcb
            -I$(srcdir)/../..                                                  \
647dcb
            -I$(srcdir)/..                                                     \
647dcb
-           -I$(srcdir)
647dcb
+           -I$(srcdir)                                                        \
647dcb
+           -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\"
647dcb
 
647dcb
 plugindir = $(libdir)/plymouth/renderers
647dcb
 plugin_LTLIBRARIES = drm.la
647dcb
 
647dcb
 drm_la_CFLAGS = $(PLYMOUTH_CFLAGS) $(DRM_CFLAGS)
647dcb
 
647dcb
 drm_la_LDFLAGS = -module -avoid-version -export-dynamic
647dcb
 drm_la_LIBADD = $(PLYMOUTH_LIBS) $(DRM_LIBS)                                  \
647dcb
                          ../../../libply/libply.la                            \
647dcb
                          ../../../libply-splash-core/libply-splash-core.la
647dcb
 drm_la_SOURCES = $(srcdir)/plugin.c
647dcb
 
647dcb
 endif
647dcb
 
647dcb
 MAINTAINERCLEANFILES = Makefile.in
647dcb
diff --git a/src/plugins/renderers/drm/plugin.c b/src/plugins/renderers/drm/plugin.c
647dcb
index 4dbf8da..38bae36 100644
647dcb
--- a/src/plugins/renderers/drm/plugin.c
647dcb
+++ b/src/plugins/renderers/drm/plugin.c
647dcb
@@ -131,73 +131,79 @@ typedef struct
647dcb
         bool connected;
647dcb
         bool uses_hw_rotation;
647dcb
 } ply_output_t;
647dcb
 
647dcb
 struct _ply_renderer_backend
647dcb
 {
647dcb
         ply_event_loop_t                *loop;
647dcb
         ply_terminal_t                  *terminal;
647dcb
 
647dcb
         int                              device_fd;
647dcb
         char                            *device_name;
647dcb
         drmModeRes                      *resources;
647dcb
 
647dcb
         ply_renderer_input_source_t      input_source;
647dcb
         ply_list_t                      *heads;
647dcb
         ply_hashtable_t                 *heads_by_controller_id;
647dcb
 
647dcb
         ply_hashtable_t                 *output_buffers;
647dcb
 
647dcb
         ply_output_t                    *outputs;
647dcb
         int                              outputs_len;
647dcb
         int                              connected_count;
647dcb
 
647dcb
         int32_t                          dither_red;
647dcb
         int32_t                          dither_green;
647dcb
         int32_t                          dither_blue;
647dcb
 
647dcb
         uint32_t                         is_active : 1;
647dcb
         uint32_t        requires_explicit_flushing : 1;
647dcb
         uint32_t                use_preferred_mode : 1;
647dcb
+        uint32_t          watching_for_termination : 1;
647dcb
 
647dcb
         int                              panel_width;
647dcb
         int                              panel_height;
647dcb
         ply_pixel_buffer_rotation_t      panel_rotation;
647dcb
         int                              panel_scale;
647dcb
 };
647dcb
 
647dcb
 ply_renderer_plugin_interface_t *ply_renderer_backend_get_interface (void);
647dcb
 static bool open_input_source (ply_renderer_backend_t      *backend,
647dcb
                                ply_renderer_input_source_t *input_source);
647dcb
 static void flush_head (ply_renderer_backend_t *backend,
647dcb
                         ply_renderer_head_t    *head);
647dcb
 
647dcb
+static void close_device (ply_renderer_backend_t *backend);
647dcb
+
647dcb
+static void watch_for_termination (ply_renderer_backend_t *backend);
647dcb
+static void stop_watching_for_termination (ply_renderer_backend_t *backend);
647dcb
+
647dcb
 /* A small helper to determine if we should try to keep the current mode
647dcb
  * or pick the best mode ourselves, we keep the current mode only if the
647dcb
  * user specified a specific mode using video= on the commandline.
647dcb
  */
647dcb
 static bool
647dcb
 should_use_preferred_mode (void)
647dcb
 {
647dcb
         bool use_preferred_mode = true;
647dcb
 
647dcb
         if (ply_kernel_command_line_get_string_after_prefix ("video="))
647dcb
                 use_preferred_mode = false;
647dcb
 
647dcb
         ply_trace ("should_use_preferred_mode: %d", use_preferred_mode);
647dcb
 
647dcb
         return use_preferred_mode;
647dcb
 }
647dcb
 
647dcb
 static bool
647dcb
 ply_renderer_buffer_map (ply_renderer_backend_t *backend,
647dcb
                          ply_renderer_buffer_t  *buffer)
647dcb
 {
647dcb
         struct drm_mode_map_dumb map_dumb_buffer_request;
647dcb
         void *map_address;
647dcb
 
647dcb
         if (buffer->map_address != MAP_FAILED) {
647dcb
                 buffer->map_count++;
647dcb
                 return true;
647dcb
         }
647dcb
 
647dcb
         memset (&map_dumb_buffer_request, 0, sizeof(struct drm_mode_map_dumb));
647dcb
@@ -918,158 +924,214 @@ static void
647dcb
 destroy_backend (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         ply_trace ("destroying renderer backend for device %s", backend->device_name);
647dcb
         free_heads (backend);
647dcb
 
647dcb
         free (backend->device_name);
647dcb
         ply_hashtable_free (backend->output_buffers);
647dcb
         ply_hashtable_free (backend->heads_by_controller_id);
647dcb
 
647dcb
         free (backend->outputs);
647dcb
         free (backend);
647dcb
 }
647dcb
 
647dcb
 static void
647dcb
 activate (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         ply_renderer_head_t *head;
647dcb
         ply_list_node_t *node;
647dcb
 
647dcb
         ply_trace ("taking master and scanning out");
647dcb
         backend->is_active = true;
647dcb
 
647dcb
         drmSetMaster (backend->device_fd);
647dcb
         node = ply_list_get_first_node (backend->heads);
647dcb
         while (node != NULL) {
647dcb
                 head = (ply_renderer_head_t *) ply_list_node_get_data (node);
647dcb
                 /* Flush out any pending drawing to the buffer */
647dcb
                 flush_head (backend, head);
647dcb
                 node = ply_list_get_next_node (backend->heads, node);
647dcb
         }
647dcb
+
647dcb
+        watch_for_termination (backend);
647dcb
 }
647dcb
 
647dcb
 static void
647dcb
 deactivate (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         ply_trace ("dropping master");
647dcb
         drmDropMaster (backend->device_fd);
647dcb
         backend->is_active = false;
647dcb
+
647dcb
+        stop_watching_for_termination (backend);
647dcb
 }
647dcb
 
647dcb
 static void
647dcb
 on_active_vt_changed (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         if (ply_terminal_is_active (backend->terminal)) {
647dcb
                 ply_trace ("activating on vt change");
647dcb
                 activate (backend);
647dcb
         } else {
647dcb
                 ply_trace ("deactivating on vt change");
647dcb
                 deactivate (backend);
647dcb
         }
647dcb
 }
647dcb
 
647dcb
 static bool
647dcb
 load_driver (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         int device_fd;
647dcb
 
647dcb
         ply_trace ("Opening '%s'", backend->device_name);
647dcb
         device_fd = open (backend->device_name, O_RDWR);
647dcb
 
647dcb
         if (device_fd < 0) {
647dcb
                 ply_trace ("open failed: %m");
647dcb
                 return false;
647dcb
         }
647dcb
 
647dcb
         backend->device_fd = device_fd;
647dcb
 
647dcb
         drmDropMaster (device_fd);
647dcb
 
647dcb
         return true;
647dcb
 }
647dcb
 
647dcb
 static void
647dcb
 unload_backend (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         if (backend == NULL)
647dcb
                 return;
647dcb
 
647dcb
         ply_trace ("unloading backend");
647dcb
 
647dcb
         if (backend->device_fd >= 0) {
647dcb
                 drmClose (backend->device_fd);
647dcb
                 backend->device_fd = -1;
647dcb
         }
647dcb
 
647dcb
         destroy_backend (backend);
647dcb
         backend = NULL;
647dcb
 
647dcb
 }
647dcb
 
647dcb
+static void
647dcb
+on_term_signal (ply_renderer_backend_t *backend)
647dcb
+{
647dcb
+        pid_t pid;
647dcb
+
647dcb
+        ply_trace ("got SIGTERM, launching drm escrow to protect splash, and dying");
647dcb
+
647dcb
+        pid = fork();
647dcb
+
647dcb
+        if (pid == 0) {
647dcb
+                const char *argv[] = { PLYMOUTH_DRM_ESCROW_DIRECTORY "/plymouthd-drm-escrow", NULL };
647dcb
+
647dcb
+                dup (backend->device_fd);
647dcb
+                execve (argv[0], (char * const *) argv, NULL);
647dcb
+
647dcb
+		ply_trace ("could not launch drm escrow process: %m");
647dcb
+
647dcb
+                _exit (1);
647dcb
+        }
647dcb
+
647dcb
+
647dcb
+	close_device (backend);
647dcb
+
647dcb
+        exit (0);
647dcb
+}
647dcb
+
647dcb
+static void
647dcb
+watch_for_termination (ply_renderer_backend_t *backend)
647dcb
+{
647dcb
+        if (backend->watching_for_termination)
647dcb
+                return;
647dcb
+
647dcb
+	ply_trace ("watching for termination signal");
647dcb
+        ply_event_loop_watch_signal (backend->loop, SIGTERM, (ply_event_handler_t) on_term_signal, backend);
647dcb
+        backend->watching_for_termination = true;
647dcb
+}
647dcb
+
647dcb
+static void
647dcb
+stop_watching_for_termination (ply_renderer_backend_t *backend)
647dcb
+{
647dcb
+        if (!backend->watching_for_termination)
647dcb
+                return;
647dcb
+
647dcb
+	ply_trace ("stopping watching for termination signal");
647dcb
+        ply_event_loop_stop_watching_signal (backend->loop, SIGTERM);
647dcb
+        backend->watching_for_termination = false;
647dcb
+}
647dcb
+
647dcb
 static bool
647dcb
 open_device (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         assert (backend != NULL);
647dcb
         assert (backend->device_name != NULL);
647dcb
 
647dcb
         if (!load_driver (backend))
647dcb
                 return false;
647dcb
 
647dcb
         if (backend->terminal == NULL)
647dcb
                 return true;
647dcb
 
647dcb
         if (!ply_terminal_open (backend->terminal)) {
647dcb
                 ply_trace ("could not open terminal: %m");
647dcb
                 return false;
647dcb
         }
647dcb
 
647dcb
         if (!ply_terminal_is_vt (backend->terminal)) {
647dcb
                 ply_trace ("terminal is not a VT");
647dcb
                 ply_terminal_close (backend->terminal);
647dcb
                 return false;
647dcb
         }
647dcb
 
647dcb
         ply_terminal_watch_for_active_vt_change (backend->terminal,
647dcb
                                                  (ply_terminal_active_vt_changed_handler_t)
647dcb
                                                  on_active_vt_changed,
647dcb
                                                  backend);
647dcb
 
647dcb
+        watch_for_termination (backend);
647dcb
+
647dcb
         return true;
647dcb
 }
647dcb
 
647dcb
 static void
647dcb
 close_device (ply_renderer_backend_t *backend)
647dcb
 {
647dcb
         ply_trace ("closing device");
647dcb
 
647dcb
         free_heads (backend);
647dcb
 
647dcb
+        stop_watching_for_termination (backend);
647dcb
+
647dcb
         if (backend->terminal != NULL) {
647dcb
                 ply_terminal_stop_watching_for_active_vt_change (backend->terminal,
647dcb
                                                                  (ply_terminal_active_vt_changed_handler_t)
647dcb
                                                                  on_active_vt_changed,
647dcb
                                                                  backend);
647dcb
         }
647dcb
 
647dcb
         unload_backend (backend);
647dcb
 }
647dcb
 
647dcb
 static void
647dcb
 output_get_controller_info (ply_renderer_backend_t *backend,
647dcb
                             drmModeConnector       *connector,
647dcb
                             ply_output_t           *output)
647dcb
 {
647dcb
         int i;
647dcb
         drmModeEncoder *encoder;
647dcb
 
647dcb
         assert (backend != NULL);
647dcb
 
647dcb
         output->possible_controllers = 0xffffffff;
647dcb
 
647dcb
         for (i = 0; i < connector->count_encoders; i++) {
647dcb
                 encoder = drmModeGetEncoder (backend->device_fd,
647dcb
                                              connector->encoders[i]);
647dcb
 
647dcb
                 if (encoder == NULL)
647dcb
                         continue;
647dcb
 
647dcb
                 if (encoder->encoder_id == connector->encoder_id && encoder->crtc_id) {
647dcb
diff --git a/src/plymouthd-drm-escrow.c b/src/plymouthd-drm-escrow.c
647dcb
new file mode 100644
647dcb
index 0000000..9097db9
647dcb
--- /dev/null
647dcb
+++ b/src/plymouthd-drm-escrow.c
647dcb
@@ -0,0 +1,18 @@
647dcb
+#include <signal.h>
647dcb
+#include <unistd.h>
647dcb
+
647dcb
+int
647dcb
+main(int argc, char **argv)
647dcb
+{
647dcb
+	signal (SIGTERM, SIG_IGN);
647dcb
+
647dcb
+        /* Make the first byte in argv be '@' so that we can survive systemd's killing
647dcb
+         * spree until the power is killed at shutdown.
647dcb
+         * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons
647dcb
+         */
647dcb
+        argv[0][0] = '@';
647dcb
+
647dcb
+        while (pause());
647dcb
+
647dcb
+        return 0;
647dcb
+}
647dcb
diff --git a/systemd-units/plymouth-halt.service.in b/systemd-units/plymouth-halt.service.in
647dcb
index cb87c1f..00f7eed 100644
647dcb
--- a/systemd-units/plymouth-halt.service.in
647dcb
+++ b/systemd-units/plymouth-halt.service.in
647dcb
@@ -1,13 +1,14 @@
647dcb
 [Unit]
647dcb
 Description=Show Plymouth Halt Screen
647dcb
 After=getty@tty1.service display-manager.service plymouth-start.service
647dcb
 Before=systemd-halt.service
647dcb
 DefaultDependencies=no
647dcb
 ConditionKernelCommandLine=!plymouth.enable=0
647dcb
 ConditionVirtualization=!container
647dcb
 
647dcb
 [Service]
647dcb
 ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=shutdown --attach-to-session
647dcb
 ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
647dcb
+KillMode=none
647dcb
 Type=forking
647dcb
 RemainAfterExit=yes
647dcb
diff --git a/systemd-units/plymouth-poweroff.service.in b/systemd-units/plymouth-poweroff.service.in
647dcb
index cf05e47..a1f78eb 100644
647dcb
--- a/systemd-units/plymouth-poweroff.service.in
647dcb
+++ b/systemd-units/plymouth-poweroff.service.in
647dcb
@@ -1,13 +1,14 @@
647dcb
 [Unit]
647dcb
 Description=Show Plymouth Power Off Screen
647dcb
 After=getty@tty1.service display-manager.service plymouth-start.service
647dcb
 Before=systemd-poweroff.service
647dcb
 DefaultDependencies=no
647dcb
 ConditionKernelCommandLine=!plymouth.enable=0
647dcb
 ConditionVirtualization=!container
647dcb
 
647dcb
 [Service]
647dcb
 ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=shutdown --attach-to-session
647dcb
 ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
647dcb
+KillMode=none
647dcb
 Type=forking
647dcb
 RemainAfterExit=yes
647dcb
diff --git a/systemd-units/plymouth-reboot.service.in b/systemd-units/plymouth-reboot.service.in
647dcb
index 3624550..8fff576 100644
647dcb
--- a/systemd-units/plymouth-reboot.service.in
647dcb
+++ b/systemd-units/plymouth-reboot.service.in
647dcb
@@ -1,13 +1,14 @@
647dcb
 [Unit]
647dcb
 Description=Show Plymouth Reboot Screen
647dcb
 After=getty@tty1.service display-manager.service plymouth-start.service
647dcb
 Before=systemd-reboot.service
647dcb
 DefaultDependencies=no
647dcb
 ConditionKernelCommandLine=!plymouth.enable=0
647dcb
 ConditionVirtualization=!container
647dcb
 
647dcb
 [Service]
647dcb
 ExecStart=@PLYMOUTH_DAEMON_DIR@/plymouthd --mode=reboot --attach-to-session
647dcb
 ExecStartPost=-@PLYMOUTH_CLIENT_DIR@/plymouth show-splash
647dcb
+KillMode=none
647dcb
 Type=forking
647dcb
 RemainAfterExit=yes
647dcb
-- 
647dcb
2.26.0
647dcb