diff --git a/toolkit/xre/nsX11ErrorHandler.cpp b/toolkit/xre/nsX11ErrorHandler.cpp index 726a809c77a5..416f8e68e5fd 100644 --- a/toolkit/xre/nsX11ErrorHandler.cpp +++ b/toolkit/xre/nsX11ErrorHandler.cpp @@ -9,12 +9,46 @@ #include "nsXULAppAPI.h" #include "nsExceptionHandler.h" #include "nsDebug.h" +#include "nsString.h" +#include "nsTArray.h" #include "mozilla/X11Util.h" #include #define BUFSIZE 2048 // What Xlib uses with XGetErrorDatabaseText +struct XExtension { + nsCString name; + int major_opcode; + + XExtension(const char* aName, int aCode) : name(aName), major_opcode(aCode) {} +}; + +static nsTArray sXExtensions; + +// 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 query the +// extension list early to avoid problems. +static void QueryXExtensions(Display* aDisplay) { + if (!aDisplay) { + return; + } + int nExts = 0; + char** extNames = XListExtensions(aDisplay, &nExts); + if (!extNames) { + return; + } + for (int i = 0; i < nExts; ++i) { + int major_opcode, first_event, first_error; + if (XQueryExtension(aDisplay, extNames[i], &major_opcode, &first_event, + &first_error)) { + sXExtensions.EmplaceBack(extNames[i], major_opcode); + } + } + XFreeExtensionList(extNames); +} + extern "C" { int X11Error(Display* display, XErrorEvent* event) { // Get an indication of how long ago the request that caused the error was @@ -28,34 +62,13 @@ int X11Error(Display* display, XErrorEvent* event) { message.AppendInt(event->request_code); } else { // Extension request - - // 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(nullptr); - if (tmpDisplay) { - int nExts; - char** extNames = XListExtensions(tmpDisplay, &nExts); - int first_error; - if (extNames) { - for (int i = 0; i < nExts; ++i) { - int major_opcode, first_event; - 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); + for (XExtension& ext : sXExtensions) { + if (ext.major_opcode == event->request_code) { + message.Append(ext.name); + message.Append('.'); + message.AppendInt(event->minor_code); + break; } - XCloseDisplay(tmpDisplay); } } @@ -130,9 +143,9 @@ int X11Error(Display* display, XErrorEvent* event) { void InstallX11ErrorHandler() { XSetErrorHandler(X11Error); - if (PR_GetEnv("MOZ_X_SYNC")) { - Display* display = mozilla::DefaultXDisplay(); - if (display) { + if (Display* display = mozilla::DefaultXDisplay()) { + QueryXExtensions(display); + if (PR_GetEnv("MOZ_X_SYNC")) { XSynchronize(display, X11True); } }