161 lines
4.4 KiB
Diff
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
|
|
|