drisw: Try harder to probe whether MIT-SHM works
authorAdam Jackson <ajax@redhat.com>
Tue, 5 Mar 2019 20:31:51 +0000 (15:31 -0500)
committerDave Airlie <airlied@redhat.com>
Mon, 8 Apr 2019 23:50:24 +0000 (09:50 +1000)
XQueryExtension merely tells you whether the extension exists, it
doesn't tell you whether you're local enough for it to work.
XShmQueryVersion is not enough to discover this either, you need to
provoke the server to do actual work, and if it thinks you're remote it
will throw BadRequest at you. So send an invalid ShmDetach and use the
error code to distinguish local from remote.

[airlied: fixed bug not resetting xshm_error to 0 on success,
which made later stuff fail completely.]

Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Adam Jackson <ajax@redhat.com>
src/glx/drisw_glx.c

index c63b097a71abe8cd9f85758967fe9a038fe10411..f38dbbca2dffee18ce327724774f9b62ba1ce65c 100644 (file)
@@ -73,11 +73,10 @@ handle_xerror(Display *dpy, XErrorEvent *event)
    (void) dpy;
 
    assert(xshm_opcode != -1);
-   if (event->request_code != xshm_opcode ||
-       event->minor_code != X_ShmAttach)
+   if (event->request_code != xshm_opcode)
       return 0;
 
-   xshm_error = 1;
+   xshm_error = event->error_code;
    return 0;
 }
 
@@ -826,9 +825,27 @@ driswBindExtensions(struct drisw_screen *psc, const __DRIextension **extensions)
 static int
 check_xshm(Display *dpy)
 {
+   int (*old_handler)(Display *, XErrorEvent *);
+
    int ignore;
+   XShmSegmentInfo info = { 0, };
+
+   if (!XQueryExtension(dpy, "MIT-SHM", &xshm_opcode, &ignore, &ignore))
+      return False;
+
+   old_handler = XSetErrorHandler(handle_xerror);
+   XShmDetach(dpy, &info);
+   XSync(dpy, False);
+   (void) XSetErrorHandler(old_handler);
 
-   return XQueryExtension(dpy, "MIT-SHM", &xshm_opcode, &ignore, &ignore);
+   /* BadRequest means we're a remote client. If we were local we'd
+    * expect BadValue since 'info' has an invalid segment name.
+    */
+   if (xshm_error == BadRequest)
+      return False;
+
+   xshm_error = 0;
+   return True;
 }
 
 static struct glx_screen *