mirror of
https://gitlab.freedesktop.org/plymouth/plymouth.git
synced 2026-05-07 02:38:07 +02:00
src: die during shutdown with everything else
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
This commit is contained in:
parent
ab986a9582
commit
00df82fea8
12 changed files with 134 additions and 13 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
11
src/main.c
11
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
18
src/plymouthd-drm-escrow.c
Normal file
18
src/plymouthd-drm-escrow.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
12
systemd-units/plymouth-switch-root-initramfs.service.in
Normal file
12
systemd-units/plymouth-switch-root-initramfs.service.in
Normal file
|
|
@ -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
|
||||
Loading…
Add table
Reference in a new issue