diff options
author | Hans de Goede <jwrdegoede@fedoraproject.org> | 2021-04-06 11:53:40 +0000 |
---|---|---|
committer | Hans de Goede <jwrdegoede@fedoraproject.org> | 2021-04-06 11:53:40 +0000 |
commit | e55447500fa95a0cc59c741296030ed91a2986dc (patch) | |
tree | 770d8e8cccbf65e4a78c6d6ba6f260b772a46fd3 | |
parent | fbe2b79da56cf0a4b7ed5ca4754449ab4875b40f (diff) | |
parent | 2a7755febb2daa92f785abb710aee00d48cb7e3a (diff) |
Merge branch 'rework-shutdown-handling' into 'master'
Rework shutdown handling
See merge request plymouth/plymouth!138
-rw-r--r-- | configure.ac | 1 | ||||
-rwxr-xr-x | scripts/plymouth-populate-initrd.in | 2 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/libply-splash-core/ply-device-manager.c | 11 | ||||
-rw-r--r-- | src/main.c | 66 | ||||
-rw-r--r-- | src/plymouthd-fd-escrow.c | 18 | ||||
-rw-r--r-- | systemd-units/Makefile.am | 37 | ||||
-rw-r--r-- | systemd-units/plymouth-switch-root-initramfs.service.in | 15 |
8 files changed, 136 insertions, 20 deletions
diff --git a/configure.ac b/configure.ac index a7b92994..9c9a3e13 100644 --- a/configure.ac +++ b/configure.ac @@ -342,6 +342,7 @@ AC_CONFIG_FILES([Makefile po/Makefile.in systemd-units/plymouth-reboot.service systemd-units/plymouth-start.service systemd-units/plymouth-switch-root.service + systemd-units/plymouth-switch-root-initramfs.service systemd-units/systemd-ask-password-plymouth.path systemd-units/systemd-ask-password-plymouth.service systemd-units/Makefile diff --git a/scripts/plymouth-populate-initrd.in b/scripts/plymouth-populate-initrd.in index 616ecc4e..0ff1f124 100755 --- a/scripts/plymouth-populate-initrd.in +++ b/scripts/plymouth-populate-initrd.in @@ -22,6 +22,7 @@ [ -z "$PLYMOUTH_POLICYDIR" ] && PLYMOUTH_POLICYDIR="@PLYMOUTH_POLICY_DIR@" [ -z "$PLYMOUTH_DAEMON_PATH" ] && PLYMOUTH_DAEMON_PATH="@PLYMOUTH_DAEMON_DIR@/plymouthd" [ -z "$PLYMOUTH_CLIENT_PATH" ] && PLYMOUTH_CLIENT_PATH="@PLYMOUTH_CLIENT_DIR@/plymouth" +[ -z "$PLYMOUTH_DRM_ESCROW_PATH" ] && PLYMOUTH_DRM_ESCROW_PATH="@PLYMOUTH_LIBEXECDIR@/plymouth/plymouthd-fd-escrow" [ -z "$SYSTEMD_UNIT_DIR" ] && SYSTEMD_UNIT_DIR="@SYSTEMD_UNIT_DIR@" # Generic substring function. If $2 is in $1, return 0. @@ -416,6 +417,7 @@ ddebug "Running with PLYMOUTH_LDD_PATH=$PLYMOUTH_LDD_PATH" mkdir -p ${INITRDDIR}${PLYMOUTH_DATADIR}/plymouth/themes inst ${PLYMOUTH_DAEMON_PATH} $INITRDDIR inst ${PLYMOUTH_CLIENT_PATH} $INITRDDIR +inst ${PLYMOUTH_DRM_ESCROW_PATH} $INITRDDIR inst ${PLYMOUTH_DATADIR}/plymouth/themes/text/text.plymouth $INITRDDIR inst ${PLYMOUTH_PLUGIN_PATH}/text.so $INITRDDIR inst ${PLYMOUTH_DATADIR}/plymouth/themes/details/details.plymouth $INITRDDIR diff --git a/src/Makefile.am b/src/Makefile.am index cbba2be4..ad3655d5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,7 @@ AM_CPPFLAGS = -I$(top_srcdir) \ -I$(srcdir)/libply-splash-core \ -I$(srcdir) \ -DPLYMOUTH_LOCALE_DIRECTORY=\"$(localedir)\" \ + -DPLYMOUTH_DRM_ESCROW_DIRECTORY=\"$(libexecdir)/plymouth\" \ -DPLYMOUTH_LOG_DIRECTORY=\"$(localstatedir)/log\" \ -DPLYMOUTH_SPOOL_DIRECTORY=\"$(localstatedir)/spool/plymouth\" \ -DPLYMOUTH_TIME_DIRECTORY=\"$(localstatedir)/lib/plymouth/\" \ @@ -31,6 +32,11 @@ plymouthd_SOURCES = \ plugins/splash/details/plugin.c \ main.c +escrowdir = $(libexecdir)/plymouth +escrow_PROGRAMS = plymouthd-fd-escrow + +plymouthd_fd_escrow_SOURCES = plymouthd-fd-escrow.c + plymouthdrundir = $(localstatedir)/run/plymouth plymouthdspooldir = $(localstatedir)/spool/plymouth plymouthdtimedir = $(localstatedir)/lib/plymouth diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index db843fc7..aed7bac2 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -189,11 +189,16 @@ free_devices_from_device_path (ply_device_manager_t *manager, ply_hashtable_remove (manager->renderers, (void *) device_path); free (key); - if (manager->renderers_activated) - ply_renderer_deactivate (renderer); + /* + * Close is false when called from ply_device_manager_free (), in this + * case we don't deactivate / close for retain-splash purposes. + */ + if (close) { + if (manager->renderers_activated) + ply_renderer_deactivate (renderer); - if (close) ply_renderer_close (renderer); + } ply_renderer_free (renderer); } @@ -158,6 +158,7 @@ static void on_quit (state_t *state, static bool sh_is_init (state_t *state); static void cancel_pending_delayed_show (state_t *state); static void prepare_logging (state_t *state); +static void dump_debug_buffer_to_file (void); static void on_session_output (state_t *state, @@ -653,6 +654,12 @@ on_newroot (state_t *state, } ply_trace ("new root mounted at \"%s\", switching to it", root_dir); + + if (!strcmp (root_dir, "/run/initramfs") && debug_buffer != NULL) { + ply_trace ("switching back to initramfs, dumping debug-buffer now"); + dump_debug_buffer_to_file (); + } + chdir (root_dir); chroot ("."); chdir ("/"); @@ -1875,8 +1882,13 @@ check_verbosity (state_t *state) } if (debug_buffer != NULL) { - if (debug_buffer_path == NULL) - debug_buffer_path = strdup (PLYMOUTH_LOG_DIRECTORY "/plymouth-debug.log"); + if (debug_buffer_path == NULL) { + if (state->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN || + state->mode == PLY_BOOT_SPLASH_MODE_REBOOT) + debug_buffer_path = strdup (PLYMOUTH_LOG_DIRECTORY "/plymouth-shutdown-debug.log"); + else + debug_buffer_path = strdup (PLYMOUTH_LOG_DIRECTORY "/plymouth-debug.log"); + } ply_logger_add_filter (ply_logger_get_error_default (), (ply_logger_filter_handler_t) @@ -2056,6 +2068,43 @@ on_crash (int signum) } static void +start_plymouthd_fd_escrow (void) +{ + pid_t pid; + + pid = fork (); + if (pid == 0) { + const char *argv[] = { PLYMOUTH_DRM_ESCROW_DIRECTORY "/plymouthd-fd-escrow", NULL }; + + execve (argv[0], (char * const *) argv, NULL); + ply_trace ("could not launch fd escrow process: %m"); + _exit (1); + } +} + +static void +on_term_signal (state_t *state) +{ + bool retain_splash = false; + + ply_trace ("received SIGTERM"); + + /* + * On shutdown/reboot with pixel-displays active, start the plymouthd-fd-escrow + * helper to hold on to the pixel-displays fds until the end. + */ + if ((state->mode == PLY_BOOT_SPLASH_MODE_SHUTDOWN || + state->mode == PLY_BOOT_SPLASH_MODE_REBOOT) && + !state->is_inactive && state->boot_splash && + ply_boot_splash_uses_pixel_displays (state->boot_splash)) { + start_plymouthd_fd_escrow (); + retain_splash = true; + } + + on_quit (state, retain_splash, ply_trigger_new (NULL)); +} + +static void write_pid_file (const char *filename) { FILE *fp; @@ -2214,11 +2263,18 @@ 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 + * Note ply_file_exists () does not work here because /etc/initrd-release + * is a symlink when using a dracut generated initrd. */ - argv[0][0] = '@'; + if (state.mode == PLY_BOOT_SPLASH_MODE_BOOT_UP && + access ("/etc/initrd-release", F_OK) >= 0) + argv[0][0] = '@'; + + /* Catch SIGTERM for clean shutdown on poweroff/reboot */ + ply_event_loop_watch_signal (state.loop, SIGTERM, + (ply_event_handler_t) on_term_signal, &state); state.boot_server = start_boot_server (&state); diff --git a/src/plymouthd-fd-escrow.c b/src/plymouthd-fd-escrow.c new file mode 100644 index 00000000..89ec5b68 --- /dev/null +++ b/src/plymouthd-fd-escrow.c @@ -0,0 +1,18 @@ +#include <signal.h> +#include <unistd.h> + +int +main(int argc, char **argv) +{ + signal (SIGTERM, SIG_IGN); + + /* Make the first byte in argv be '@' so that we can survive systemd's killing + * spree until the power is killed at shutdown. + * http://www.freedesktop.org/wiki/Software/systemd/RootStorageDaemons + */ + argv[0][0] = '@'; + + while (pause()); + + return 0; +} diff --git a/systemd-units/Makefile.am b/systemd-units/Makefile.am index b1d843b6..cd2d7be5 100644 --- a/systemd-units/Makefile.am +++ b/systemd-units/Makefile.am @@ -1,5 +1,6 @@ systemd_unit_templates = \ plymouth-switch-root.service.in \ + plymouth-switch-root-initramfs.service.in \ plymouth-start.service.in \ plymouth-read-write.service.in \ plymouth-quit.service.in \ @@ -37,17 +38,25 @@ 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) + rm -f plymouth-kexec.service \ + plymouth-switch-root-initramfs.service && \ + $(LN_S) ../plymouth-kexec.service && \ + $(LN_S) ../plymouth-switch-root-initramfs.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-initramfs.service) (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 +66,17 @@ 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) + rm -f plymouth-kexec.service \ + plymouth-switch-root-initramfs.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/poweroff.target.wants && \ - rm -f plymouth-poweroff.service) + rm -f plymouth-poweroff.service \ + plymouth-switch-root-initramfs.service) (cd $(DESTDIR)$(SYSTEMD_UNIT_DIR)/halt.target.wants && \ - rm -f plymouth-halt.service) + rm -f plymouth-halt.service \ + plymouth-switch-root-initramfs.service) rmdir --ignore-fail-on-non-empty \ $(DESTDIR)$(SYSTEMD_UNIT_DIR)/sysinit.target.wants \ $(DESTDIR)$(SYSTEMD_UNIT_DIR)/multi-user.target.wants \ diff --git a/systemd-units/plymouth-switch-root-initramfs.service.in b/systemd-units/plymouth-switch-root-initramfs.service.in new file mode 100644 index 00000000..0610803c --- /dev/null +++ b/systemd-units/plymouth-switch-root-initramfs.service.in @@ -0,0 +1,15 @@ +[Unit] +Description=Tell Plymouth To Jump To initramfs +DefaultDependencies=no +# dracut-shutdown.service restores the initramfs when it is _stopped_ +# use Conflicts to make sure its ExecStop has run before we do +Conflicts=dracut-shutdown.service +After=plymouth-halt.service plymouth-reboot.service plymouth-poweroff.service plymouth-kexec.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 |