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 "nsXULAppAPI.h" | ||||||
| #include "nsExceptionHandler.h" | #include "nsExceptionHandler.h" | ||||||
| #include "nsDebug.h" | #include "nsDebug.h" | ||||||
|  | #include "nsString.h" | ||||||
|  | #include "nsTArray.h" | ||||||
| 
 | 
 | ||||||
| #include "mozilla/X11Util.h" | #include "mozilla/X11Util.h" | ||||||
| #include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||||
| 
 | 
 | ||||||
| #define BUFSIZE 2048  // What Xlib uses with XGetErrorDatabaseText
 | #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" { | extern "C" { | ||||||
| int X11Error(Display* display, XErrorEvent* event) { | int X11Error(Display* display, XErrorEvent* event) { | ||||||
|   // Get an indication of how long ago the request that caused the error was
 |   // Get an indication of how long ago the request that caused the error was
 | ||||||
|  | @ -28,35 +62,14 @@ int X11Error(Display* display, XErrorEvent* event) { | ||||||
|     message.AppendInt(event->request_code); |     message.AppendInt(event->request_code); | ||||||
|   } else { |   } else { | ||||||
|     // Extension request
 |     // Extension request
 | ||||||
| 
 |     for (XExtension& ext : sXExtensions) { | ||||||
|     // man XSetErrorHandler says "the error handler should not call any
 |       if (ext.major_opcode == event->request_code) { | ||||||
|     // functions (directly or indirectly) on the display that will generate
 |         message.Append(ext.name); | ||||||
|     // 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.Append('.'); | ||||||
|         message.AppendInt(event->minor_code); |         message.AppendInt(event->minor_code); | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|         XFreeExtensionList(extNames); |  | ||||||
|       } |  | ||||||
|       XCloseDisplay(tmpDisplay); |  | ||||||
|     } |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   char buffer[BUFSIZE]; |   char buffer[BUFSIZE]; | ||||||
|  | @ -130,9 +143,9 @@ int X11Error(Display* display, XErrorEvent* event) { | ||||||
| void InstallX11ErrorHandler() { | void InstallX11ErrorHandler() { | ||||||
|   XSetErrorHandler(X11Error); |   XSetErrorHandler(X11Error); | ||||||
| 
 | 
 | ||||||
|  |   if (Display* display = mozilla::DefaultXDisplay()) { | ||||||
|  |     QueryXExtensions(display); | ||||||
|     if (PR_GetEnv("MOZ_X_SYNC")) { |     if (PR_GetEnv("MOZ_X_SYNC")) { | ||||||
|     Display* display = mozilla::DefaultXDisplay(); |  | ||||||
|     if (display) { |  | ||||||
|       XSynchronize(display, X11True); |       XSynchronize(display, X11True); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Lee Salzman
						Lee Salzman