forked from mirrors/gecko-dev
Bug 1774916 - Avoid opening temporary X display in error handler. r=aosmond,gfx-reviewers,nical
Differential Revision: https://phabricator.services.mozilla.com/D150401
This commit is contained in:
parent
a504ef6021
commit
8f14cd2cd5
1 changed files with 43 additions and 30 deletions
|
|
@ -9,12 +9,46 @@
|
|||
#include "nsXULAppAPI.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "mozilla/X11Util.h"
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#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<XExtension> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue