After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 753434 - mutter is always using /dev/dri/card0
mutter is always using /dev/dri/card0
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: wayland
git master
Other Linux
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
: 756051 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2015-08-10 07:25 UTC by Marek Chalupa
Modified: 2015-10-05 06:50 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Use udev to find the master drm device (3.39 KB, patch)
2015-09-01 07:40 UTC, Marek Chalupa
none Details | Review
fix handling errors in meta_launcher_new (2.46 KB, patch)
2015-09-03 15:56 UTC, Marek Chalupa
none Details | Review
Find device that has boot_vga flag set (4.85 KB, patch)
2015-09-03 15:57 UTC, Marek Chalupa
none Details | Review
Refactor handling errors in meta-launcher (4.98 KB, patch)
2015-09-07 08:20 UTC, Marek Chalupa
none Details | Review
Find the right drm device (4.75 KB, patch)
2015-09-07 08:21 UTC, Marek Chalupa
none Details | Review
native: remove obsolete comment (942 bytes, patch)
2015-09-07 08:21 UTC, Marek Chalupa
committed Details | Review
Simplify getting session proxy (1.53 KB, patch)
2015-09-07 12:08 UTC, Marek Chalupa
committed Details | Review
Refactor handling errors in meta-launcher (4.71 KB, patch)
2015-09-07 12:08 UTC, Marek Chalupa
none Details | Review
Find the right drm device (4.79 KB, patch)
2015-09-07 12:09 UTC, Marek Chalupa
none Details | Review

Description Marek Chalupa 2015-08-10 07:25:31 UTC
Mutter opens /dev/dri/card0 and passes given fd to clutter, which in turns passes it to cogl which tries to use it. This is fine unless user has hybrid graphics card. In that case the /dev/dri/card0 may not be the right card.

https://bugs.freedesktop.org/show_bug.cgi?id=91474
Comment 1 Daniel Stone 2015-08-14 13:08:28 UTC
It can also break if you have the 'vgem' virtual device, which will often land in card0 before any real hardware has been probed. That could at least be trivially eliminated by checking if the device is KMS at all, and skipping it if not.
Comment 2 Ray Strode [halfline] 2015-08-31 23:46:30 UTC
some discussion in bug 753531 comment 54 about this.
Comment 3 Marek Chalupa 2015-09-01 06:43:57 UTC
(In reply to Ray Strode [halfline] from comment #2)
> some discussion in bug 753531 comment 54 about this.

Just yesterday before going home I wrote a patch for this bug. I'll check the discussion and possibly fix the patch and send it here. Thanks
Comment 4 Marek Chalupa 2015-09-01 07:40:51 UTC
Created attachment 310397 [details] [review]
Use udev to find the master drm device
Comment 5 Ray Strode [halfline] 2015-09-01 18:41:35 UTC
Review of attachment 310397 [details] [review]:

Hey this is great, thanks for working on this.
Ultimately, we'll want to use egl apis directly for device enumeration, but those apis aren't in yet, so I think this makes sense interim.

Your commit message should say "Find the device that has the boot_vga flag set"

::: src/backends/native/meta-launcher.c
@@ +265,3 @@
 
+/* get path to devnode with boot_vga flag set
+ * or fall back to /dev/dri/card0 if no such device

why are you we falling back?

@@ +269,3 @@
+ * or length of the written string (in snprintf way) */
+static gint
+get_primary_gpu_path(gchar *path, size_t maxlen)

parameters should be on separate lines.
I think it would be more idiomatic of the mutter codebase to return allocated memory instead of writing into a static buffer.
(also it's only run once, so the cost of the allocation is negligible)

@@ +272,3 @@
+{
+  const gchar *subsystems[] = {"drm", NULL};
+  GList *devs, *tmp;

i'd call devs "device_matches" and "tmp" "node" but that's just my style so whatever.

@@ +273,3 @@
+  const gchar *subsystems[] = {"drm", NULL};
+  GList *devs, *tmp;
+  GUdevDevice *pci;

this declaration should go in the loop. i'd call it pci_device

@@ +280,3 @@
+
+  g_udev_enumerator_add_match_name (enumerator, "card*");
+  g_udev_enumerator_add_match_tag (enumerator, "seat");

so you make sure the card has a seat tag here, which is good, but you don't make sure ID_SEAT matches the current seat below. (though ID_SEAT=seat0 is optional so the code should handle ID_SEAT missing for seat0)

@@ +284,3 @@
+  devs = g_udev_enumerator_execute (enumerator);
+  if (!devs)
+    goto out;

so you don't fallback actually you goto out. i think that's right.

@@ +288,3 @@
+  tmp = devs;
+  while (tmp)
+    {

maybe make this a for loop so you don't have tmp = g_list_next (tmp) repeated 3 times. doing so will futureproof the code against inadvertent infinite loops.

also mutter tends to do tmp = tmp->next not use g_list_next

another thing, for clarity assigning tmp->data to temporary variable might make sense (i'd personally call it card_device).

@@ +289,3 @@
+  while (tmp)
+    {
+      if (!g_udev_device_get_device_file (tmp->data))

this should probably have comment like "filter out connector devices like card0-SVIDEO-1" or something.

doing g_udev_device_get_device_type (device) == G_UDEV_DEVICE_TYPE_CHAR would be more specific and then you wouldn't be getting the name and not doing anything with it.

@@ +302,3 @@
+        }
+
+      /* get value of boot_vga attribute or 0 if the device has no boot_vga */

this comment should say "check if the device was used for output at boot time"

@@ +315,3 @@
+  /* if no device satisfy, fall back to /dev/dri/card0 */
+  if (!tmp)
+    retval = snprintf (path, maxlen, "/dev/dri/card0");

i don't think we should do this.

@@ +345,3 @@
+    }
+  else if (retval >= (int) sizeof path)
+    g_error ("buffer too short for the path");

yea that g_error is ugly, just just g_strdup() on the result.
Comment 6 Marek Chalupa 2015-09-03 13:03:15 UTC
> @@ +280,3 @@
> +
> +  g_udev_enumerator_add_match_name (enumerator, "card*");
> +  g_udev_enumerator_add_match_tag (enumerator, "seat");
> 
> so you make sure the card has a seat tag here, which is good, but you don't
> make sure ID_SEAT matches the current seat below. (though ID_SEAT=seat0 is
> optional so the code should handle ID_SEAT missing for seat0)

How can I get the current seat id from Login1Seat (or any other way)? meta-wayland-seat.c hardcodes seat0 to wl_seat_send_name(), but I suppose we don't want that here.

> maybe make this a for loop so you don't have tmp = g_list_next (tmp)
> repeated 3 times. doing so will futureproof the code against inadvertent
> infinite loops

Yeah, that sounds right
Comment 7 Ray Strode [halfline] 2015-09-03 13:27:46 UTC
well, you can query it from the Login1Seat proxy using the "id" property, but I wouldn't do that. The easiest way is probably the XDG_SEAT environment variable. The slightly more robust way is to query the session with:

sd_pid_get_session(0, &session);

and then get the seat associated with the session with 

sd_session_get_seat (session, &seat);

Doing it that way is nicer than using the bus, since it reads the information straight from the logind database instead of having logind read it from the database and then having ipc in between. 

Though, thinking about it the bus proxy may already have the "id" property cached as long as it was started without G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES so maybe it would be fine to use it after all.
Comment 8 Marek Chalupa 2015-09-03 15:56:05 UTC
(In reply to Ray Strode [halfline] from comment #7)
> well, you can query it from the Login1Seat proxy using the "id" property,
> but I wouldn't do that. The easiest way is probably the XDG_SEAT environment
> variable. The slightly more robust way is to query the session with:
> 
> sd_pid_get_session(0, &session);
> 
> and then get the seat associated with the session with 
> 
> sd_session_get_seat (session, &seat);
> 
> Doing it that way is nicer than using the bus, since it reads the
> information straight from the logind database instead of having logind read
> it from the database and then having ipc in between. 
> 
> Though, thinking about it the bus proxy may already have the "id" property
> cached as long as it was started without
> G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES so maybe it would be fine to use
> it after all.

Trying to get the seat id from cache did not work, so I used the sd_* functions. When I was trying to get the cached information, I needed to refactor meta_launcher_new to get the seat proxy before calling get_kms_fd. Although I don't need it with sd_.* functions, I changed the patch a little bit and attaching it too.
Comment 9 Marek Chalupa 2015-09-03 15:56:43 UTC
Created attachment 310609 [details] [review]
fix handling errors in meta_launcher_new
Comment 10 Marek Chalupa 2015-09-03 15:57:16 UTC
Created attachment 310610 [details] [review]
Find device that has boot_vga flag set
Comment 11 Ray Strode [halfline] 2015-09-03 16:26:16 UTC
Review of attachment 310609 [details] [review]:

Thanks, this is a good clean up.

::: src/backends/native/meta-backend-native.c
@@ -329,3 @@
   MetaBackendNativePrivate *priv = meta_backend_native_get_instance_private (native);
 
-  /* We're a display server, so start talking to weston-launch. */

This should probably be a separate commit, since it doesn't have anything to do with error handling.

@@ +331,3 @@
   priv->launcher = meta_launcher_new ();
+  if (!priv->launcher)
+    g_error ("Failed initializing the backend");

This doesn't give any indication on why the failure happened.  We did get indication from within the function, though, as g_warnings.

I think either, meta_launcher_new should take a GError * and this code should print why it's failing, or the g_warnings in meta_launcher_new() should get turned into g_errors' and this check should get dropped.

::: src/backends/native/meta-launcher.c
@@ +299,3 @@
   int kms_fd;
 
   session_proxy = get_session_proxy (NULL);

get_session_proxy should propagate its error.

@@ +307,3 @@
       g_warning ("Could not take control: %s", error->message);
       g_error_free (error);
+      goto out_session;

mutter doesn't normally have multiple out labels in one function.
A more typical approach would be to initialize each variable to NULL and do

g_clear_object (&session_proxy);
g_clear_object (&seat_proxy);

after a lone out: label. of course that's just a subjective style issue, so whatever.

@@ +310,3 @@
     }
 
+  seat_proxy = get_seat_proxy (NULL);

get_seat_proxy should propagate its error
Comment 12 Ray Strode [halfline] 2015-09-03 16:39:45 UTC
Review of attachment 310610 [details] [review]:

looking good. just a couple minor things

::: src/backends/native/meta-launcher.c
@@ +57,2 @@
 static Login1Session *
+get_session_proxy (char *session_id, GCancellable *cancellable)

parameters should be on separate lines, and session_id should be const char *.

Though in this case, I don't think you need to pass session_id in. just change the
object path below to "/org/freedesktop/login1/session/self" then session_id won't be needed
at all (which will also prevent the need to escape the object path below)

@@ +286,3 @@
+      const gchar *device_seat;
+
+      /* filter out devices that are not character device */

maybe add an example, e.g., ", like card0-DVI-I-1"

@@ +307,3 @@
+      g_object_unref (pci_device);
+
+      if (boot_vga == 1)

this should probably be if (boot_vga == 1 || g_strcmp0 (seat_name, "seat0") != 0) (or something like that). If hardware is explicitly assigned to a non-seat0 seat then we'll want to use it, even though it wasn't used at boot time.

@@ +309,3 @@
+      if (boot_vga == 1)
+        {
+          /* found the boot_vga device */

and if that if statement is changed then this comment needs to be updated

@@ +326,3 @@
 static gboolean
 get_kms_fd (Login1Session *session_proxy,
+            gchar *seat_id,

this should be const gchar *

@@ +372,3 @@
   int kms_fd;
 
+  if (sd_pid_get_session (getpid (), &session_id) < 0)

you can use 0 here instead of getpid (), but getpid() is fine.  I guess it's more self documenting.
Comment 13 Ray Strode [halfline] 2015-09-05 11:50:02 UTC
Review of attachment 310610 [details] [review]:

::: src/backends/native/meta-launcher.c
@@ +368,3 @@
   Login1Session *session_proxy;
   Login1Seat *seat_proxy;
+  char *session_id, *seat_id;

oh one other thing is these need to be freed with free() when you're done with them.
Comment 14 Marek Chalupa 2015-09-07 08:20:48 UTC
Created attachment 310779 [details] [review]
Refactor handling errors in meta-launcher
Comment 15 Marek Chalupa 2015-09-07 08:21:09 UTC
Created attachment 310780 [details] [review]
Find the right drm device
Comment 16 Marek Chalupa 2015-09-07 08:21:28 UTC
Created attachment 310781 [details] [review]
native: remove obsolete comment
Comment 17 Ray Strode [halfline] 2015-09-07 11:01:12 UTC
Review of attachment 310779 [details] [review]:

hey thanks, i know the scope of your changes expanded a bit and I appreciate the effort.
Feel free to commit this. I have a few suggestions below you can take or leave first. up to you.

::: src/backends/native/meta-launcher.c
@@ +56,3 @@
+static void
+report_login1_error(const char *prefix,
+                    GError *error)

probably should be called report_error_and_die or something like that.  I mean there's nothing login1 specific about it other than you're only presently using it for logind related stuff.

@@ +63,3 @@
+    g_error ("%s: %s", prefix, error->message);
+  else
+    g_error (prefix);

So the GError doesn't get freed.  That's fine since g_error is fatal anyway, but I'd add a comment anyway, like:

/* At this point we should be dead, so we don't need to free the GError */

Coverity may also complain, but coverity is too hard to predict anyway, so let's cross that bridge when we come to it.

@@ -67,1 @@
 

So I know I told you to make this change, but it doesn't actually match the description in your commit message. I'd either split it out as a separate commit up front, or, at least, highlight it in the commit body.
Comment 18 Ray Strode [halfline] 2015-09-07 11:22:00 UTC
Review of attachment 310780 [details] [review]:

Looks good. Feel free to commit after fixing upt he style issues.

::: src/backends/native/meta-launcher.c
@@ +277,3 @@
 
+static gchar *
+get_primary_gpu_path(const gchar *seat_name)

missing space here

@@ +293,3 @@
+    goto out;
+
+  for(tmp = devices; tmp != NULL; tmp = tmp->next)

missing space here

@@ +307,3 @@
+      if (!device_seat)
+        /* when ID_SEAT is not set, it means seat0 */
+        device_seat = "seat0";

should have braces here since you have braces in the else

@@ +316,3 @@
+        }
+
+      /* check if the device belongs to our seat */

should probably say "skip devices that don't belong to our seat". Your way isn't wrong, but strcmp semantics are confusing enough that someone quickly skimming the code might interpret your comment to mean to continue if the device belongs.

@@ +357,3 @@
+  path = get_primary_gpu_path(seat_id);
+  if (!path)
+    g_error ("could not get drm master device");

it doesn't actually get master until later, so calling it the "master device" is a little confusing. you could call it the "drm card device" or "drm modesetting device" or "drm kms device" maybe. also maybe "find" instead of "get" ?

@@ +380,3 @@
+  /* on error the seat_id will remain NULL */
+  sd_session_get_seat (session_id, &seat_id);
+  free(session_id);

missing space

@@ +400,3 @@
+  seat_id = get_seat_id ();
+  if (!seat_id)
+    g_error ("Failed getting seat id");

would be nice if we could report the error code here, but I guess not critical.
Comment 19 Ray Strode [halfline] 2015-09-07 11:22:39 UTC
Review of attachment 310781 [details] [review]:

++
Comment 20 Marek Chalupa 2015-09-07 12:07:53 UTC
> So I know I told you to make this change, but it doesn't actually match the
> description in your commit message. I'd either split it out as a separate
> commit up front, or, at least, highlight it in the commit body.

Will split it to separate patch.

Regarding commiting the patches - I do not have permissions to do that, so it'd be great if you (or anybody) could commit it for me
Comment 21 Marek Chalupa 2015-09-07 12:08:24 UTC
Created attachment 310808 [details] [review]
Simplify getting session proxy
Comment 22 Marek Chalupa 2015-09-07 12:08:54 UTC
Created attachment 310809 [details] [review]
Refactor handling errors in meta-launcher
Comment 23 Marek Chalupa 2015-09-07 12:09:16 UTC
Created attachment 310810 [details] [review]
Find the right drm device
Comment 24 Ray Strode [halfline] 2015-09-07 12:42:56 UTC
Comment on attachment 310781 [details] [review]
native: remove obsolete comment

Attachment 310781 [details] pushed as c13ddaf - native: remove obsolete comment
Comment 25 Ray Strode [halfline] 2015-09-07 12:45:09 UTC
Comment on attachment 310808 [details] [review]
Simplify getting session proxy

Attachment 310808 [details] pushed as 8e22bf5
Comment 26 Ray Strode [halfline] 2015-09-07 12:48:01 UTC
Attachment 310809 [details] pushed as 1845bfe
Attachment 310810 [details] pushed as 79f755b

(some git-bz screw up here, but should be set)
Comment 27 Jonas Ådahl 2015-09-17 03:57:22 UTC
The commit 

commit 8e22bf5bc96a7d9ff1aba8ea8217a4c3ca06b4ce
Author: Marek Chalupa <mchqwerty@gmail.com>
Date:   Mon Sep 7 13:38:49 2015 +0200

    launcher: simplify getting session dbus proxy
    
    Use path "/org/freedesktop/login1/session/self" instead of
    getting session id and building the path manually
    
    https://bugzilla.gnome.org/show_bug.cgi?id=753434

breaks VT switching for me (running jhbuild on top of Fedora 22). Reverting it makes it work again.
Comment 28 Jasper St. Pierre (not reading bugmail) 2015-09-17 04:09:35 UTC
Yeah. Revert it. It's an idea that doesn't work, since signals are sent to the specific session ID.
Comment 29 Jonas Ådahl 2015-09-17 04:19:37 UTC
Ok. Pushed the revert to master, with the reason you mentioned in the commit message. Thanks.
Comment 30 Ray Strode [halfline] 2015-09-17 04:33:09 UTC
thanks for tracking the bug down.  

technically we're in code freeze I think, but this is a serious enough issue that I doubt release-team would be against the revert. 

Still, can you shoot a mail to the release-team list to let them know?
Comment 31 Jonas Ådahl 2015-09-17 04:34:38 UTC
Ah, right. I'll send a mail.
Comment 32 Jasper St. Pierre (not reading bugmail) 2015-09-17 05:13:16 UTC
Sorry, I would have caught it, but I'm a little bit out of the loop for GNOME / mutter stuff lately.
Comment 33 Martin Kupec 2015-10-05 06:50:54 UTC
*** Bug 756051 has been marked as a duplicate of this bug. ***