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