b=576933 use a separate display to make protocol requests within X error handler r=roc
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 25 Mar 2011 16:38:59 +1300
changeset 63423 5eeb8a849e746bcd43b347cca5a7fee4c6100624
parent 63422 1bf2d5b7a2d2c605b401790eaa5a700b7b11ba6d
child 63424 b9af0765d235bbd0a968c3775ada81463f4ac18a
push id67
push userktomlinson@mozilla.com
push dateWed, 13 Apr 2011 17:25:58 +0000
reviewersroc
bugs576933
milestone2.0.1pre
b=576933 use a separate display to make protocol requests within X error handler r=roc
toolkit/xre/nsX11ErrorHandler.cpp
--- a/toolkit/xre/nsX11ErrorHandler.cpp
+++ b/toolkit/xre/nsX11ErrorHandler.cpp
@@ -50,56 +50,58 @@ using mozilla::plugins::PluginProcessChi
 
 #include "mozilla/X11Util.h"
 #include <X11/Xlib.h>
 
 #define BUFSIZE 2048 // What Xlib uses with XGetErrorDatabaseText
 
 extern "C" {
 static int
-IgnoreError(Display *display, XErrorEvent *event) {
-  return 0; // This return value is ignored.
-}
-
-static int
 X11Error(Display *display, XErrorEvent *event) {
   nsCAutoString notes;
   char buffer[BUFSIZE];
 
   // Get an indication of how long ago the request that caused the error was
-  // made.  Do this before querying extensions etc below.
+  // made.
   unsigned long age = NextRequest(display) - event->serial;
 
-  // Ignore subsequent errors, which may get processed during the extension
-  // queries below for example.
-  XSetErrorHandler(IgnoreError);
-
   // Get a string to represent the request that caused the error.
   nsCAutoString message;
   if (event->request_code < 128) {
     // Core protocol request
     message.AppendInt(event->request_code);
   } else {
     // Extension request
-    int nExts;
-    char** extNames = XListExtensions(display, &nExts);
-    if (extNames) {
-      for (int i = 0; i < nExts; ++i) {
-        int major_opcode, first_event, first_error;
-        if (XQueryExtension(display, extNames[i],
-                            &major_opcode, &first_event, &first_error)
-            && major_opcode == event->request_code) {
-          message.Append(extNames[i]);
-          message.Append('.');
-          message.AppendInt(event->minor_code);
-          break;
+
+    // man XSetErrorHandler says "the error handler should not call any
+    // functions (directly or indirectly) on the display that will generate
+    // protocol requests or that will look for input events" so we use another
+    // temporary Display to request extension information.  This assumes on
+    // the DISPLAY environment variable has been set and matches what was used
+    // to open |display|.
+    Display *tmpDisplay = XOpenDisplay(NULL);
+    if (tmpDisplay) {
+      int nExts;
+      char** extNames = XListExtensions(tmpDisplay, &nExts);
+      if (extNames) {
+        for (int i = 0; i < nExts; ++i) {
+          int major_opcode, first_event, first_error;
+          if (XQueryExtension(tmpDisplay, extNames[i],
+                              &major_opcode, &first_event, &first_error)
+              && major_opcode == event->request_code) {
+            message.Append(extNames[i]);
+            message.Append('.');
+            message.AppendInt(event->minor_code);
+            break;
+          }
         }
+
+        XFreeExtensionList(extNames);
       }
-
-      XFreeExtensionList(extNames);
+      XCloseDisplay(tmpDisplay);
     }
   }
 
   if (message.IsEmpty()) {
     buffer[0] = '\0';
   } else {
     XGetErrorDatabaseText(display, "XRequest", message.get(), "",
                           buffer, sizeof(buffer));