Blame SOURCES/0001-device-manager-don-t-watch-for-udev-events-when-deac.patch

2836bb
From b5bacf2b5e5d9e58cbe96fda0a56baf5dfa11358 Mon Sep 17 00:00:00 2001
2836bb
From: Ray Strode <rstrode@redhat.com>
2836bb
Date: Wed, 10 Oct 2018 20:07:37 +0100
2836bb
Subject: [PATCH] device-manager: don't watch for udev events when deactivated
2836bb
2836bb
If a device gets added when we're already deactivated, plymouth shouldn't
2836bb
process the device, since processing it effectively activates plymouth.
2836bb
2836bb
This commit pulls the udev monitor fd out of the event loop while
2836bb
plymouth is deactivated so new events are deferred until reactivation.
2836bb
2836bb
Modified by Iain Lane <iain.lane@canonical.com>: Also deactivate the
2836bb
timer that finds all devices known to udev after an interval, when
2836bb
paused.
2836bb
---
2836bb
 src/libply-splash-core/ply-device-manager.c | 74 +++++++++++++++++----
2836bb
 src/libply-splash-core/ply-device-manager.h |  2 +
2836bb
 src/main.c                                  |  3 +
2836bb
 3 files changed, 67 insertions(+), 12 deletions(-)
2836bb
2836bb
diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
2836bb
index b637fb8..82f0137 100644
2836bb
--- a/src/libply-splash-core/ply-device-manager.c
2836bb
+++ b/src/libply-splash-core/ply-device-manager.c
2836bb
@@ -36,74 +36,78 @@
2836bb
 
2836bb
 #include "ply-logger.h"
2836bb
 #include "ply-event-loop.h"
2836bb
 #include "ply-hashtable.h"
2836bb
 #include "ply-list.h"
2836bb
 #include "ply-utils.h"
2836bb
 
2836bb
 #define SUBSYSTEM_DRM "drm"
2836bb
 #define SUBSYSTEM_FRAME_BUFFER "graphics"
2836bb
 
2836bb
 #ifdef HAVE_UDEV
2836bb
 static void create_devices_from_udev (ply_device_manager_t *manager);
2836bb
 #endif
2836bb
 
2836bb
 static bool create_devices_for_terminal_and_renderer_type (ply_device_manager_t *manager,
2836bb
                                                            const char           *device_path,
2836bb
                                                            ply_terminal_t       *terminal,
2836bb
                                                            ply_renderer_type_t   renderer_type);
2836bb
 struct _ply_device_manager
2836bb
 {
2836bb
         ply_device_manager_flags_t flags;
2836bb
         ply_event_loop_t          *loop;
2836bb
         ply_hashtable_t           *terminals;
2836bb
         ply_hashtable_t           *renderers;
2836bb
         ply_terminal_t            *local_console_terminal;
2836bb
         ply_list_t                *keyboards;
2836bb
         ply_list_t                *text_displays;
2836bb
         ply_list_t                *pixel_displays;
2836bb
         struct udev               *udev_context;
2836bb
         struct udev_monitor       *udev_monitor;
2836bb
+        ply_fd_watch_t            *fd_watch;
2836bb
 
2836bb
         ply_keyboard_added_handler_t         keyboard_added_handler;
2836bb
         ply_keyboard_removed_handler_t       keyboard_removed_handler;
2836bb
         ply_pixel_display_added_handler_t    pixel_display_added_handler;
2836bb
         ply_pixel_display_removed_handler_t  pixel_display_removed_handler;
2836bb
         ply_text_display_added_handler_t     text_display_added_handler;
2836bb
         ply_text_display_removed_handler_t   text_display_removed_handler;
2836bb
         void                                *event_handler_data;
2836bb
 
2836bb
         uint32_t                    local_console_managed : 1;
2836bb
         uint32_t                    local_console_is_text : 1;
2836bb
         uint32_t                    serial_consoles_detected : 1;
2836bb
         uint32_t                    renderers_activated : 1;
2836bb
         uint32_t                    keyboards_activated : 1;
2836bb
+
2836bb
+        uint32_t                    paused : 1;
2836bb
+        uint32_t                    device_timeout_elapsed : 1;
2836bb
 };
2836bb
 
2836bb
 static void
2836bb
 detach_from_event_loop (ply_device_manager_t *manager)
2836bb
 {
2836bb
         assert (manager != NULL);
2836bb
 
2836bb
         manager->loop = NULL;
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 attach_to_event_loop (ply_device_manager_t *manager,
2836bb
                       ply_event_loop_t     *loop)
2836bb
 {
2836bb
         assert (manager != NULL);
2836bb
         assert (loop != NULL);
2836bb
         assert (manager->loop == NULL);
2836bb
 
2836bb
         manager->loop = loop;
2836bb
 
2836bb
         ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
2836bb
                                        detach_from_event_loop,
2836bb
                                        manager);
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 free_displays_for_renderer (ply_device_manager_t *manager,
2836bb
                             ply_renderer_t       *renderer)
2836bb
 {
2836bb
         ply_list_node_t *node;
2836bb
@@ -348,77 +352,92 @@ on_udev_event (ply_device_manager_t *manager)
2836bb
                 return;
2836bb
 
2836bb
         if (strcmp (action, "add") == 0) {
2836bb
                 const char *subsystem;
2836bb
 
2836bb
                 subsystem = udev_device_get_subsystem (device);
2836bb
 
2836bb
                 if (strcmp (subsystem, SUBSYSTEM_DRM) == 0) {
2836bb
                         if (manager->local_console_managed && manager->local_console_is_text)
2836bb
                                 ply_trace ("ignoring since we're already using text splash for local console");
2836bb
                         else
2836bb
                                 create_devices_for_udev_device (manager, device);
2836bb
                 } else {
2836bb
                         ply_trace ("ignoring since we only handle subsystem %s devices after timeout", subsystem);
2836bb
                 }
2836bb
         } else if (strcmp (action, "remove") == 0) {
2836bb
                 free_devices_for_udev_device (manager, device);
2836bb
         }
2836bb
 
2836bb
         udev_device_unref (device);
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 watch_for_udev_events (ply_device_manager_t *manager)
2836bb
 {
2836bb
         int fd;
2836bb
 
2836bb
         assert (manager != NULL);
2836bb
         assert (manager->udev_monitor == NULL);
2836bb
 
2836bb
+        if (manager->fd_watch != NULL)
2836bb
+                return;
2836bb
+
2836bb
         ply_trace ("watching for udev graphics device add and remove events");
2836bb
 
2836bb
-        manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev");
2836bb
+        if (manager->udev_monitor == NULL) {
2836bb
+                manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev");
2836bb
 
2836bb
-        udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL);
2836bb
-        udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL);
2836bb
-        udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat");
2836bb
-        udev_monitor_enable_receiving (manager->udev_monitor);
2836bb
+                udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL);
2836bb
+                udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL);
2836bb
+                udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat");
2836bb
+                udev_monitor_enable_receiving (manager->udev_monitor);
2836bb
+        }
2836bb
 
2836bb
         fd = udev_monitor_get_fd (manager->udev_monitor);
2836bb
-        ply_event_loop_watch_fd (manager->loop,
2836bb
-                                 fd,
2836bb
-                                 PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
2836bb
-                                 (ply_event_handler_t)
2836bb
-                                 on_udev_event,
2836bb
-                                 NULL,
2836bb
-                                 manager);
2836bb
+        manager->fd_watch = ply_event_loop_watch_fd (manager->loop,
2836bb
+                                                     fd,
2836bb
+                                                     PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
2836bb
+                                                     (ply_event_handler_t)
2836bb
+                                                     on_udev_event,
2836bb
+                                                     NULL,
2836bb
+                                                     manager);
2836bb
+}
2836bb
+
2836bb
+static void
2836bb
+stop_watching_for_udev_events (ply_device_manager_t *manager)
2836bb
+{
2836bb
+        if (manager->fd_watch == NULL)
2836bb
+                return;
2836bb
+
2836bb
+        ply_event_loop_stop_watching_fd (manager->loop, manager->fd_watch);
2836bb
+        manager->fd_watch = NULL;
2836bb
 }
2836bb
 #endif
2836bb
 
2836bb
 static void
2836bb
 free_terminal (char                 *device,
2836bb
                ply_terminal_t       *terminal,
2836bb
                ply_device_manager_t *manager)
2836bb
 {
2836bb
         ply_hashtable_remove (manager->terminals, device);
2836bb
 
2836bb
         ply_terminal_free (terminal);
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 free_terminals (ply_device_manager_t *manager)
2836bb
 {
2836bb
         ply_hashtable_foreach (manager->terminals,
2836bb
                                (ply_hashtable_foreach_func_t *)
2836bb
                                free_terminal,
2836bb
                                manager);
2836bb
 }
2836bb
 
2836bb
 static ply_terminal_t *
2836bb
 get_terminal (ply_device_manager_t *manager,
2836bb
               const char           *device_name)
2836bb
 {
2836bb
         char *full_name = NULL;
2836bb
         ply_terminal_t *terminal;
2836bb
 
2836bb
         if (strncmp (device_name, "/dev/", strlen ("/dev/")) == 0)
2836bb
@@ -774,60 +793,67 @@ create_devices_from_terminals (ply_device_manager_t *manager)
2836bb
 
2836bb
         if (has_serial_consoles) {
2836bb
                 ply_trace ("serial consoles detected, managing them with details forced");
2836bb
                 manager->serial_consoles_detected = true;
2836bb
 
2836bb
                 ply_hashtable_foreach (manager->terminals,
2836bb
                                        (ply_hashtable_foreach_func_t *)
2836bb
                                        create_devices_for_terminal,
2836bb
                                        manager);
2836bb
                 return true;
2836bb
         }
2836bb
 
2836bb
         return false;
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 create_non_graphical_devices (ply_device_manager_t *manager)
2836bb
 {
2836bb
         create_devices_for_terminal_and_renderer_type (manager,
2836bb
                                                        NULL,
2836bb
                                                        manager->local_console_terminal,
2836bb
                                                        PLY_RENDERER_TYPE_NONE);
2836bb
 }
2836bb
 
2836bb
 #ifdef HAVE_UDEV
2836bb
 static void
2836bb
 create_devices_from_udev (ply_device_manager_t *manager)
2836bb
 {
2836bb
         bool found_drm_device, found_fb_device;
2836bb
 
2836bb
+        manager->device_timeout_elapsed = true;
2836bb
+
2836bb
+        if (manager->paused) {
2836bb
+                ply_trace ("create_devices_from_udev timeout elapsed while paused, deferring execution");
2836bb
+                return;
2836bb
+        }
2836bb
+
2836bb
         ply_trace ("Timeout elapsed, looking for devices from udev");
2836bb
 
2836bb
         found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
2836bb
         found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
2836bb
 
2836bb
         if (found_drm_device || found_fb_device)
2836bb
                 return;
2836bb
 
2836bb
         ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware");
2836bb
         create_non_graphical_devices (manager);
2836bb
 }
2836bb
 #endif
2836bb
 
2836bb
 static void
2836bb
 create_fallback_devices (ply_device_manager_t *manager)
2836bb
 {
2836bb
         create_devices_for_terminal_and_renderer_type (manager,
2836bb
                                                        NULL,
2836bb
                                                        manager->local_console_terminal,
2836bb
                                                        PLY_RENDERER_TYPE_AUTO);
2836bb
 }
2836bb
 
2836bb
 void
2836bb
 ply_device_manager_watch_devices (ply_device_manager_t                *manager,
2836bb
                                   double                               device_timeout,
2836bb
                                   ply_keyboard_added_handler_t         keyboard_added_handler,
2836bb
                                   ply_keyboard_removed_handler_t       keyboard_removed_handler,
2836bb
                                   ply_pixel_display_added_handler_t    pixel_display_added_handler,
2836bb
                                   ply_pixel_display_removed_handler_t  pixel_display_removed_handler,
2836bb
                                   ply_text_display_added_handler_t     text_display_added_handler,
2836bb
@@ -965,30 +991,54 @@ ply_device_manager_activate_keyboards (ply_device_manager_t *manager)
2836bb
 
2836bb
                 ply_keyboard_watch_for_input (keyboard);
2836bb
 
2836bb
                 node = next_node;
2836bb
         }
2836bb
 
2836bb
         manager->keyboards_activated = true;
2836bb
 }
2836bb
 
2836bb
 void
2836bb
 ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager)
2836bb
 {
2836bb
         ply_list_node_t *node;
2836bb
 
2836bb
         ply_trace ("deactivating keyboards");
2836bb
         node = ply_list_get_first_node (manager->keyboards);
2836bb
         while (node != NULL) {
2836bb
                 ply_keyboard_t *keyboard;
2836bb
                 ply_list_node_t *next_node;
2836bb
 
2836bb
                 keyboard = ply_list_node_get_data (node);
2836bb
                 next_node = ply_list_get_next_node (manager->keyboards, node);
2836bb
 
2836bb
                 ply_keyboard_stop_watching_for_input (keyboard);
2836bb
 
2836bb
                 node = next_node;
2836bb
         }
2836bb
 
2836bb
         manager->keyboards_activated = false;
2836bb
 }
2836bb
+
2836bb
+void
2836bb
+ply_device_manager_pause (ply_device_manager_t *manager)
2836bb
+{
2836bb
+        ply_trace ("ply_device_manager_pause() called, stopping watching for udev events");
2836bb
+        manager->paused = true;
2836bb
+#ifdef HAVE_UDEV
2836bb
+        stop_watching_for_udev_events (manager);
2836bb
+#endif
2836bb
+}
2836bb
+
2836bb
+void
2836bb
+ply_device_manager_unpause (ply_device_manager_t *manager)
2836bb
+{
2836bb
+        ply_trace ("ply_device_manager_unpause() called, resuming watching for udev events");
2836bb
+        manager->paused = false;
2836bb
+#ifdef HAVE_UDEV
2836bb
+        if (manager->device_timeout_elapsed) {
2836bb
+                ply_trace ("ply_device_manager_unpause(): timeout elapsed while paused, looking for udev devices");
2836bb
+                create_devices_from_udev (manager);
2836bb
+        }
2836bb
+        watch_for_udev_events (manager);
2836bb
+#endif
2836bb
+}
2836bb
diff --git a/src/libply-splash-core/ply-device-manager.h b/src/libply-splash-core/ply-device-manager.h
2836bb
index ad05897..389b636 100644
2836bb
--- a/src/libply-splash-core/ply-device-manager.h
2836bb
+++ b/src/libply-splash-core/ply-device-manager.h
2836bb
@@ -28,46 +28,48 @@
2836bb
 #include "ply-text-display.h"
2836bb
 
2836bb
 typedef enum
2836bb
 {
2836bb
         PLY_DEVICE_MANAGER_FLAGS_NONE = 0,
2836bb
         PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES = 1 << 0,
2836bb
         PLY_DEVICE_MANAGER_FLAGS_IGNORE_UDEV = 1 << 1,
2836bb
         PLY_DEVICE_MANAGER_FLAGS_SKIP_RENDERERS = 1 << 2
2836bb
 } ply_device_manager_flags_t;
2836bb
 
2836bb
 typedef struct _ply_device_manager ply_device_manager_t;
2836bb
 typedef void (* ply_keyboard_added_handler_t) (void *, ply_keyboard_t *);
2836bb
 typedef void (* ply_keyboard_removed_handler_t) (void *, ply_keyboard_t *);
2836bb
 typedef void (* ply_pixel_display_added_handler_t) (void *, ply_pixel_display_t *);
2836bb
 typedef void (* ply_pixel_display_removed_handler_t) (void *, ply_pixel_display_t *);
2836bb
 typedef void (* ply_text_display_added_handler_t) (void *, ply_text_display_t *);
2836bb
 typedef void (* ply_text_display_removed_handler_t) (void *, ply_text_display_t *);
2836bb
 
2836bb
 #ifndef PLY_HIDE_FUNCTION_DECLARATIONS
2836bb
 ply_device_manager_t *ply_device_manager_new (const char                *default_tty,
2836bb
                                               ply_device_manager_flags_t flags);
2836bb
 void ply_device_manager_watch_devices (ply_device_manager_t                *manager,
2836bb
                                        double                               device_timeout,
2836bb
                                        ply_keyboard_added_handler_t         keyboard_added_handler,
2836bb
                                        ply_keyboard_removed_handler_t       keyboard_removed_handler,
2836bb
                                        ply_pixel_display_added_handler_t    pixel_display_added_handler,
2836bb
                                        ply_pixel_display_removed_handler_t  pixel_display_removed_handler,
2836bb
                                        ply_text_display_added_handler_t     text_display_added_handler,
2836bb
                                        ply_text_display_removed_handler_t   text_display_removed_handler,
2836bb
                                        void                                *data);
2836bb
+void ply_device_manager_pause (ply_device_manager_t *manager);
2836bb
+void ply_device_manager_unpause (ply_device_manager_t *manager);
2836bb
 bool ply_device_manager_has_serial_consoles (ply_device_manager_t *manager);
2836bb
 bool ply_device_manager_has_displays (ply_device_manager_t *manager);
2836bb
 ply_list_t *ply_device_manager_get_keyboards (ply_device_manager_t *manager);
2836bb
 ply_list_t *ply_device_manager_get_pixel_displays (ply_device_manager_t *manager);
2836bb
 ply_list_t *ply_device_manager_get_text_displays (ply_device_manager_t *manager);
2836bb
 void ply_device_manager_free (ply_device_manager_t *manager);
2836bb
 void ply_device_manager_activate_keyboards (ply_device_manager_t *manager);
2836bb
 void ply_device_manager_deactivate_keyboards (ply_device_manager_t *manager);
2836bb
 void ply_device_manager_activate_renderers (ply_device_manager_t *manager);
2836bb
 void ply_device_manager_deactivate_renderers (ply_device_manager_t *manager);
2836bb
 ply_terminal_t *ply_device_manager_get_default_terminal (ply_device_manager_t *manager);
2836bb
 
2836bb
 #endif
2836bb
 
2836bb
 #endif
2836bb
 /* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */
2836bb
diff --git a/src/main.c b/src/main.c
2836bb
index e44de7b..3253aa9 100644
2836bb
--- a/src/main.c
2836bb
+++ b/src/main.c
2836bb
@@ -1305,94 +1305,97 @@ on_boot_splash_idle (state_t *state)
2836bb
                 ply_trace ("quitting program");
2836bb
                 quit_program (state);
2836bb
         } else if (state->deactivate_trigger != NULL) {
2836bb
                 ply_trace ("deactivating splash");
2836bb
                 deactivate_splash (state);
2836bb
         }
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 on_deactivate (state_t       *state,
2836bb
                ply_trigger_t *deactivate_trigger)
2836bb
 {
2836bb
         if (state->is_inactive) {
2836bb
                 ply_trigger_pull (deactivate_trigger, NULL);
2836bb
                 return;
2836bb
         }
2836bb
 
2836bb
         if (state->deactivate_trigger != NULL) {
2836bb
                 ply_trigger_add_handler (state->deactivate_trigger,
2836bb
                                          (ply_trigger_handler_t)
2836bb
                                          ply_trigger_pull,
2836bb
                                          deactivate_trigger);
2836bb
                 return;
2836bb
         }
2836bb
 
2836bb
         state->deactivate_trigger = deactivate_trigger;
2836bb
 
2836bb
         ply_trace ("deactivating");
2836bb
         cancel_pending_delayed_show (state);
2836bb
 
2836bb
+        ply_device_manager_pause (state->device_manager);
2836bb
         ply_device_manager_deactivate_keyboards (state->device_manager);
2836bb
 
2836bb
         if (state->boot_splash != NULL) {
2836bb
                 ply_boot_splash_become_idle (state->boot_splash,
2836bb
                                              (ply_boot_splash_on_idle_handler_t)
2836bb
                                              on_boot_splash_idle,
2836bb
                                              state);
2836bb
         } else {
2836bb
                 ply_trace ("deactivating splash");
2836bb
                 deactivate_splash (state);
2836bb
         }
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 on_reactivate (state_t *state)
2836bb
 {
2836bb
         if (!state->is_inactive)
2836bb
                 return;
2836bb
 
2836bb
         if (state->local_console_terminal != NULL) {
2836bb
                 ply_terminal_open (state->local_console_terminal);
2836bb
                 ply_terminal_watch_for_vt_changes (state->local_console_terminal);
2836bb
                 ply_terminal_set_unbuffered_input (state->local_console_terminal);
2836bb
                 ply_terminal_ignore_mode_changes (state->local_console_terminal, false);
2836bb
         }
2836bb
 
2836bb
         if ((state->session != NULL) && state->should_be_attached) {
2836bb
                 ply_trace ("reactivating terminal session");
2836bb
                 attach_to_running_session (state);
2836bb
         }
2836bb
 
2836bb
         ply_device_manager_activate_keyboards (state->device_manager);
2836bb
         ply_device_manager_activate_renderers (state->device_manager);
2836bb
 
2836bb
+        ply_device_manager_unpause (state->device_manager);
2836bb
+
2836bb
         state->is_inactive = false;
2836bb
 
2836bb
         update_display (state);
2836bb
 }
2836bb
 
2836bb
 static void
2836bb
 on_quit (state_t       *state,
2836bb
          bool           retain_splash,
2836bb
          ply_trigger_t *quit_trigger)
2836bb
 {
2836bb
         ply_trace ("quitting (retain splash: %s)", retain_splash ? "true" : "false");
2836bb
 
2836bb
         if (state->quit_trigger != NULL) {
2836bb
                 ply_trace ("quit trigger already pending, so chaining to it");
2836bb
                 ply_trigger_add_handler (state->quit_trigger,
2836bb
                                          (ply_trigger_handler_t)
2836bb
                                          ply_trigger_pull,
2836bb
                                          quit_trigger);
2836bb
                 return;
2836bb
         }
2836bb
 
2836bb
         if (state->system_initialized) {
2836bb
                 ply_trace ("system initialized so saving boot-duration file");
2836bb
                 ply_create_directory (PLYMOUTH_TIME_DIRECTORY);
2836bb
                 ply_progress_save_cache (state->progress,
2836bb
                                          get_cache_file_for_mode (state->mode));
2836bb
         } else {
2836bb
                 ply_trace ("system not initialized so skipping saving boot-duration file");
2836bb
         }
2836bb
         state->quit_trigger = quit_trigger;
2836bb
-- 
2836bb
2.21.0
2836bb