alaurie / rpms / plymouth

Forked from rpms/plymouth 4 days ago
Clone

Blame SOURCES/0001-ply-device-manager-Fix-race-causing-undesired-creati.patch

ff86aa
From f76757f9dd63407686b24c98e5c2290502bcbb93 Mon Sep 17 00:00:00 2001
ff86aa
From: Hans de Goede <hdegoede@redhat.com>
ff86aa
Date: Tue, 26 Mar 2019 15:10:28 -0400
ff86aa
Subject: [PATCH] ply-device-manager: Fix race causing undesired creation of
ff86aa
 non-gfx devs
ff86aa
ff86aa
On systems with working drm/kms devices we still sometimes see:
ff86aa
"Creating non-graphical devices, since there's no suitable graphics hardware"
ff86aa
in the logs (and actually create non-gfx devices).
ff86aa
ff86aa
This is caused by a race where the create_devices_from_udev timeout handler
ff86aa
runs just after the pivot-root, just at the time when the "udev trigger"
ff86aa
from the real root is done.
ff86aa
ff86aa
This causes create_devices_for_subsystem() to hit the "it's not initialized"
ff86aa
code-path for all drm and fb devices, even though before (from the initrd)
ff86aa
drm-devices where already setup successfully.
ff86aa
ff86aa
One way of solving this would be to stop the timer as soon as we successfully
ff86aa
enumerate the first drm device. But we need the timer to enumerate fb devices
ff86aa
so on machines where some outputs only have a fbdev driver (corner case) this
ff86aa
would break support for those outputs.
ff86aa
ff86aa
Instead this commit moves the found_drm_device and found_fb_device to the
ff86aa
global manager state and sets them from create_devices_for_udev_device().
ff86aa
This way they will be set when we check them from the create_devices_from_udev
ff86aa
timeout handler even if create_devices_for_subsystem skips over the devices
ff86aa
because of the udev trigger race.
ff86aa
ff86aa
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
ff86aa
---
ff86aa
 src/libply-splash-core/ply-device-manager.c |  19 +-
ff86aa
 1 files changed, 63 insertions(+), 60 deletions(-)
ff86aa
ff86aa
diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
ff86aa
index 3a2db06..b6437c5 100644
ff86aa
--- a/src/libply-splash-core/ply-device-manager.c
ff86aa
+++ b/src/libply-splash-core/ply-device-manager.c
ff86aa
@@ -47,60 +47,63 @@ static bool create_devices_for_terminal_and_renderer_type (ply_device_manager_t
ff86aa
                                                            ply_renderer_type_t   renderer_type);
ff86aa
 struct _ply_device_manager
ff86aa
 {
ff86aa
   ply_device_manager_flags_t  flags;
ff86aa
   ply_event_loop_t           *loop;
ff86aa
   ply_hashtable_t            *terminals;
ff86aa
   ply_hashtable_t            *renderers;
ff86aa
   ply_terminal_t             *local_console_terminal;
ff86aa
   ply_list_t                 *keyboards;
ff86aa
   ply_list_t                 *text_displays;
ff86aa
   ply_list_t                 *pixel_displays;
ff86aa
   struct udev                *udev_context;
ff86aa
   struct udev_queue          *udev_queue;
ff86aa
   int                         udev_queue_fd;
ff86aa
   ply_fd_watch_t             *udev_queue_fd_watch;
ff86aa
   struct udev_monitor        *udev_monitor;
ff86aa
 
ff86aa
   ply_keyboard_added_handler_t         keyboard_added_handler;
ff86aa
   ply_keyboard_removed_handler_t       keyboard_removed_handler;
ff86aa
   ply_pixel_display_added_handler_t    pixel_display_added_handler;
ff86aa
   ply_pixel_display_removed_handler_t  pixel_display_removed_handler;
ff86aa
   ply_text_display_added_handler_t     text_display_added_handler;
ff86aa
   ply_text_display_removed_handler_t   text_display_removed_handler;
ff86aa
   void                                *event_handler_data;
ff86aa
 
ff86aa
   uint32_t                    local_console_managed : 1;
ff86aa
   uint32_t                    local_console_is_text : 1;
ff86aa
   uint32_t                    serial_consoles_detected : 1;
ff86aa
   uint32_t                    renderers_activated : 1;
ff86aa
   uint32_t                    keyboards_activated : 1;
ff86aa
+
ff86aa
+  uint32_t                    found_drm_device : 1;
ff86aa
+  uint32_t                    found_fb_device : 1;
ff86aa
 };
ff86aa
 
ff86aa
 static void
ff86aa
 detach_from_event_loop (ply_device_manager_t *manager)
ff86aa
 {
ff86aa
   assert (manager != NULL);
ff86aa
 
ff86aa
   manager->loop = NULL;
ff86aa
 }
ff86aa
 
ff86aa
 static void
ff86aa
 attach_to_event_loop (ply_device_manager_t *manager,
ff86aa
                       ply_event_loop_t     *loop)
ff86aa
 {
ff86aa
   assert (manager != NULL);
ff86aa
   assert (loop != NULL);
ff86aa
   assert (manager->loop == NULL);
ff86aa
 
ff86aa
   manager->loop = loop;
ff86aa
 
ff86aa
   ply_event_loop_watch_for_exit (loop, (ply_event_loop_exit_handler_t)
ff86aa
                                  detach_from_event_loop,
ff86aa
                                  manager);
ff86aa
 }
ff86aa
 
ff86aa
 static bool
ff86aa
 drm_device_in_use (ply_device_manager_t *manager,
ff86aa
                    const char           *device_path)
ff86aa
 {
ff86aa
   ply_renderer_t *renderer;
ff86aa
@@ -183,60 +186,68 @@ create_devices_for_udev_device (ply_device_manager_t *manager,
ff86aa
         {
ff86aa
           ply_trace ("found DRM device %s", device_path);
ff86aa
           renderer_type = PLY_RENDERER_TYPE_DRM;
ff86aa
         }
ff86aa
       else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0)
ff86aa
         {
ff86aa
           ply_trace ("found frame buffer device %s", device_path);
ff86aa
           if (!fb_device_has_drm_device (manager, device))
ff86aa
             {
ff86aa
               renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER;
ff86aa
             }
ff86aa
           else
ff86aa
             {
ff86aa
               ply_trace ("ignoring, since there's a DRM device associated with it");
ff86aa
             }
ff86aa
         }
ff86aa
 
ff86aa
       if (renderer_type != PLY_RENDERER_TYPE_NONE)
ff86aa
         {
ff86aa
           ply_terminal_t *terminal = NULL;
ff86aa
 
ff86aa
           if (!manager->local_console_managed)
ff86aa
             {
ff86aa
               terminal = manager->local_console_terminal;
ff86aa
             }
ff86aa
 
ff86aa
           created = create_devices_for_terminal_and_renderer_type (manager,
ff86aa
                                                                    device_path,
ff86aa
                                                                    terminal,
ff86aa
                                                                    renderer_type);
ff86aa
+
ff86aa
+          if (created)
ff86aa
+            {
ff86aa
+              if (renderer_type == PLY_RENDERER_TYPE_DRM)
ff86aa
+                manager->found_drm_device = 1;
ff86aa
+              if (renderer_type == PLY_RENDERER_TYPE_FRAME_BUFFER)
ff86aa
+                manager->found_fb_device = 1;
ff86aa
+            }
ff86aa
        }
ff86aa
     }
ff86aa
     return created;
ff86aa
 }
ff86aa
 
ff86aa
 static void
ff86aa
 free_displays_for_renderer (ply_device_manager_t *manager,
ff86aa
                             ply_renderer_t       *renderer)
ff86aa
 {
ff86aa
   ply_list_node_t *node;
ff86aa
 
ff86aa
   node = ply_list_get_first_node (manager->pixel_displays);
ff86aa
   while (node != NULL)
ff86aa
     {
ff86aa
       ply_list_node_t *next_node;
ff86aa
       ply_pixel_display_t *display;
ff86aa
       ply_renderer_t *display_renderer;
ff86aa
 
ff86aa
       display = ply_list_node_get_data (node);
ff86aa
       next_node = ply_list_get_next_node (manager->pixel_displays, node);
ff86aa
       display_renderer = ply_pixel_display_get_renderer (display);
ff86aa
 
ff86aa
       if (display_renderer == renderer)
ff86aa
         {
ff86aa
           if (manager->pixel_display_removed_handler != NULL)
ff86aa
             manager->pixel_display_removed_handler (manager->event_handler_data, display);
ff86aa
 
ff86aa
           ply_pixel_display_free (display);
ff86aa
           ply_list_remove_node (manager->pixel_displays, node);
ff86aa
         }
ff86aa
@@ -782,68 +793,66 @@ create_devices_from_terminals (ply_device_manager_t *manager)
ff86aa
   ply_trace ("checking for consoles");
ff86aa
 
ff86aa
   if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES)
ff86aa
     {
ff86aa
       has_serial_consoles = false;
ff86aa
       ply_trace ("ignoring all consoles but default console because explicitly told to.");
ff86aa
     }
ff86aa
   else
ff86aa
     {
ff86aa
       has_serial_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active");
ff86aa
     }
ff86aa
 
ff86aa
   if (has_serial_consoles)
ff86aa
     {
ff86aa
       ply_trace ("serial consoles detected, managing them with details forced");
ff86aa
       manager->serial_consoles_detected = true;
ff86aa
 
ff86aa
       ply_hashtable_foreach (manager->terminals,
ff86aa
                              (ply_hashtable_foreach_func_t *)
ff86aa
                              create_devices_for_terminal,
ff86aa
                              manager);
ff86aa
       return true;
ff86aa
     }
ff86aa
 
ff86aa
   return false;
ff86aa
 }
ff86aa
 
ff86aa
 static void
ff86aa
 create_devices_from_udev (ply_device_manager_t *manager)
ff86aa
 {
ff86aa
-  bool found_drm_device, found_fb_device;
ff86aa
-
ff86aa
   ply_trace ("Looking for devices from udev");
ff86aa
 
ff86aa
-  found_drm_device = create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
ff86aa
-  found_fb_device = create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
ff86aa
+  create_devices_for_subsystem (manager, SUBSYSTEM_DRM);
ff86aa
+  create_devices_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
ff86aa
 
ff86aa
-  if (found_drm_device || found_fb_device)
ff86aa
+  if (manager->found_drm_device || manager->found_fb_device)
ff86aa
     return;
ff86aa
 
ff86aa
   ply_trace ("Creating non-graphical devices, since there's no suitable graphics hardware");
ff86aa
   create_devices_for_terminal_and_renderer_type (manager,
ff86aa
                                                  ply_terminal_get_name (manager->local_console_terminal),
ff86aa
                                                  manager->local_console_terminal,
ff86aa
                                                  PLY_RENDERER_TYPE_NONE);
ff86aa
 }
ff86aa
 
ff86aa
 static void
ff86aa
 create_fallback_devices (ply_device_manager_t *manager)
ff86aa
 {
ff86aa
   create_devices_for_terminal_and_renderer_type (manager,
ff86aa
                                                  ply_terminal_get_name (manager->local_console_terminal),
ff86aa
                                                  manager->local_console_terminal,
ff86aa
                                                  PLY_RENDERER_TYPE_AUTO);
ff86aa
 }
ff86aa
 
ff86aa
 static void
ff86aa
 on_udev_queue_changed (ply_device_manager_t *manager)
ff86aa
 {
ff86aa
 
ff86aa
   if (!udev_queue_get_queue_is_empty (manager->udev_queue))
ff86aa
     return;
ff86aa
 
ff86aa
   ply_trace ("udev coldplug complete");
ff86aa
   ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch);
ff86aa
   manager->udev_queue_fd_watch = NULL;
ff86aa
   udev_queue_unref (manager->udev_queue);
ff86aa
 
ff86aa
-- 
ff86aa
2.20.1
ff86aa