Files
main/desktop/misc/gdm/files/0004-gdm-CanGraphical-wait-meson.patch
2024-06-01 19:40:14 +03:00

161 lines
4.4 KiB
Diff

--- a/meson.build 2021-03-21 16:32:37.222883748 +0100
+++ b/meson.build 2021-03-21 16:32:42.114763457 +0100
@@ -38,6 +38,7 @@
# Dependencies
udev_dep = dependency('udev')
+gudev_dep = dependency('gudev-1.0')
glib_min_version = '2.56.0'
--- a/data/meson.build 2021-03-21 16:07:53.023644342 +0100
+++ b/data/meson.build 2021-03-21 16:09:14.557724574 +0100
@@ -161,6 +161,7 @@
# DBus service files
service_config = configuration_data()
service_config.set('sbindir', gdm_prefix / get_option('sbindir'))
+service_config.set('libexecdir', gdm_prefix / get_option('libexecdir'))
service_config.set('GDM_INITIAL_VT', get_option('initial-vt'))
service_config.set('LANG_CONFIG_FILE', lang_config_file)
if plymouth_dep.found()
--- a/data/gdm.service.in
+++ b/data/gdm.service.in
@@ -30,6 +30,7 @@ StandardError=inherit
EnvironmentFile=-@LANG_CONFIG_FILE@
ExecReload=/bin/kill -SIGHUP $MAINPID
KeyringMode=shared
+ExecStartPre=@libexecdir@/gdm-wait-for-drm
[Install]
Alias=display-manager.service
--- a/utils/meson.build.ori 2021-03-21 16:15:47.036216779 +0100
+++ b/utils/meson.build 2021-03-21 16:15:25.328751199 +0100
@@ -39,3 +39,16 @@
install_dir: get_option('libexecdir'),
)
+# gdm-wait-for-drm
+gdm_wait_for_drm_deps = [
+ glib_dep,
+ gudev_dep
+]
+
+gdm_wait_for_drm = executable('gdm-wait-for-drm',
+ 'gdm-wait-for-drm.c',
+ dependencies: gdm_wait_for_drm_deps,
+ include_directories: config_h_dir,
+ install: true,
+ install_dir: get_option('libexecdir'),
+)
--- /dev/null
+++ b/utils/gdm-wait-for-drm.c
@@ -0,0 +1,101 @@
+#include <glib.h>
+#include <gudev/gudev.h>
+
+/*
+ * Workaround for LP: #1794280.
+ *
+ * That bug is because the DRM device isn't ready by the time GDM tries to
+ * start wayland/X.
+ * This is a script to add to ExecStartPre of gdm.service. It does the
+ * following:
+ *
+ * 1. Enumerate drm devices from udev, looking for a DRM master. If found,
+ * exit.
+ * 2. Connect to the 'uevent' signal of gudev, watching for the same to be
+ * added. Again exit if any are found.
+ * 3. If, after 10 seconds, we haven't seen anything, try to proceed anyway as
+ * a failsafe.
+ */
+
+static gboolean
+handle_device (GUdevDevice *device)
+{
+ const gchar * const * tags;
+ tags = g_udev_device_get_tags (device);
+ g_debug ("%s\n", g_udev_device_get_name (device));
+ if (g_strv_contains (tags, "master-of-seat"))
+ {
+ g_debug (" is seat master\n");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+uevent_cb (GUdevClient *client G_GNUC_UNUSED,
+ gchar *action,
+ GUdevDevice *device,
+ gpointer user_data)
+{
+ GMainLoop *loop;
+
+ g_debug ("uevent action: %s\n", action);
+
+ loop = (GMainLoop *) user_data;
+
+ if (g_strcmp0 (action, "add") == 0)
+ {
+ if (handle_device (device))
+ {
+ g_debug (" this is good\n");
+ g_main_loop_quit (loop);
+ }
+ else
+ {
+ g_debug (" this is bad\n");
+ }
+ }
+}
+
+int
+main()
+{
+ const gchar * const subsystems[] = { "drm", NULL };
+
+ g_autoptr(GList) devices = NULL;
+ g_autoptr(GMainLoop) loop = NULL;
+ g_autoptr(GUdevClient) udev_client = NULL;
+ g_autoptr(GUdevEnumerator) enumerator = NULL;
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ udev_client = g_udev_client_new (subsystems);
+ enumerator = g_udev_enumerator_new (udev_client);
+ g_udev_enumerator_add_match_is_initialized (enumerator);
+ g_udev_enumerator_add_match_subsystem (enumerator, "drm");
+
+ devices = g_udev_enumerator_execute (enumerator);
+
+ g_debug ("enumerating devices...\n");
+
+ for (GList *l = devices; l != NULL; l = l->next)
+ {
+ g_autoptr(GUdevDevice) device = G_UDEV_DEVICE (l->data);
+
+ if (handle_device (device))
+ {
+ g_debug (" good enough for gdm\n");
+ return EXIT_SUCCESS;
+ }
+ }
+
+ g_signal_connect (udev_client, "uevent", G_CALLBACK (uevent_cb), loop);
+
+ /* after 10 seconds we try anyway */
+ g_timeout_add_seconds (10, (GSourceFunc) g_main_loop_quit, loop);
+
+ g_main_loop_run (loop);
+
+ return EXIT_SUCCESS;
+}
--
2.17.0