Index: ui/base/x/x11_util.cc |
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc |
index 39c2cff7c6f098fd1a951ce4113924f20b23bc70..0dd6e9c618db8793cf3ef12a7e1891de81503509 100644 |
--- a/ui/base/x/x11_util.cc |
+++ b/ui/base/x/x11_util.cc |
@@ -65,6 +65,8 @@ CachedPictFormats* get_cached_pict_formats() { |
const size_t kMaxCacheSize = 5; |
int DefaultX11ErrorHandler(Display* d, XErrorEvent* e) { |
+ DCHECK(!MessageLoop::current() || |
+ MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
MessageLoop::current()->PostTask( |
FROM_HERE, NewRunnableFunction(LogErrorEventDescription, d, *e)); |
return 0; |
@@ -76,6 +78,14 @@ int DefaultX11IOErrorHandler(Display* d) { |
_exit(1); |
} |
+XErrorHandler current_error_handler = DefaultX11ErrorHandler; |
+XErrorEvent last_error_event = {0, NULL, 0, 0, 0, 0, 0 }; |
+ |
+int BaseX11ErrorHandler(Display* d, XErrorEvent* e) { |
+ last_error_event = *e; |
+ return current_error_handler(d, e); |
+} |
+ |
Atom GetAtom(const char* name) { |
#if defined(TOOLKIT_USES_GTK) |
return gdk_x11_get_xatom_by_name_for_display( |
@@ -105,6 +115,49 @@ bool GetProperty(XID window, const std::string& property_name, long max_length, |
property); |
} |
+std::string BuildX11ErrorString(const XErrorEvent& error_event) { |
+ char error_str[256]; |
+ char request_str[256]; |
+ |
+ XGetErrorText(error_event.display, error_event.error_code, error_str, |
+ sizeof(error_str)); |
+ |
+ strncpy(request_str, "Unknown", sizeof(request_str)); |
+ if (error_event.request_code < 128) { |
+ std::string num = base::UintToString(error_event.request_code); |
+ XGetErrorDatabaseText(error_event.display, "XRequest", num.c_str(), |
+ "Unknown", request_str, sizeof(request_str)); |
+ } else { |
+ int num_ext; |
+ char** ext_list = XListExtensions(error_event.display, &num_ext); |
+ |
+ for (int i = 0; i < num_ext; i++) { |
+ int ext_code, first_event, first_error; |
+ XQueryExtension(error_event.display, ext_list[i], &ext_code, &first_event, |
+ &first_error); |
+ if (error_event.request_code == ext_code) { |
+ std::string msg = StringPrintf( |
+ "%s.%d", ext_list[i], error_event.minor_code); |
+ XGetErrorDatabaseText(error_event.display, "XRequest", msg.c_str(), |
+ "Unknown", request_str, sizeof(request_str)); |
+ break; |
+ } |
+ } |
+ XFreeExtensionList(ext_list); |
+ } |
+ |
+ std::ostringstream error_ss; |
+ error_ss << "X Error detected: " |
+ << "serial " << error_event.serial << ", " |
+ << "error_code " << static_cast<int>(error_event.error_code) |
+ << " (" << error_str << "), " |
+ << "request_code " << static_cast<int>(error_event.request_code) |
+ << ", " |
+ << "minor_code " << static_cast<int>(error_event.minor_code) |
+ << " (" << request_str << ")"; |
+ return error_ss.str(); |
+} |
+ |
} // namespace |
bool XDisplayExists() { |
@@ -695,6 +748,7 @@ bool ChangeWindowDesktop(XID window, XID destination) { |
} |
void SetDefaultX11ErrorHandlers() { |
+ XSetErrorHandler(BaseX11ErrorHandler); |
SetX11ErrorHandlers(NULL, NULL); |
} |
@@ -730,6 +784,15 @@ bool IsX11WindowFullScreen(XID window) { |
#endif |
} |
+void CheckForReportedX11Error() { |
+ DCHECK(!MessageLoop::current() || |
+ MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
+ if (!last_error_event.display) |
+ return; |
+ XSync(last_error_event.display, False); |
+ LOG(FATAL) << BuildX11ErrorString(last_error_event); |
+} |
+ |
// ---------------------------------------------------------------------------- |
// These functions are declared in x11_util_internal.h because they require |
// XLib.h to be included, and it conflicts with many other headers. |
@@ -808,51 +871,21 @@ XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) { |
void SetX11ErrorHandlers(XErrorHandler error_handler, |
XIOErrorHandler io_error_handler) { |
- XSetErrorHandler(error_handler ? error_handler : DefaultX11ErrorHandler); |
- XSetIOErrorHandler( |
- io_error_handler ? io_error_handler : DefaultX11IOErrorHandler); |
+ DCHECK(!MessageLoop::current() || |
+ MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
+ current_error_handler = error_handler ? |
+ error_handler : DefaultX11ErrorHandler; |
+ XSetIOErrorHandler(io_error_handler ? |
+ io_error_handler : DefaultX11IOErrorHandler); |
} |
void LogErrorEventDescription(Display* dpy, |
const XErrorEvent& error_event) { |
- char error_str[256]; |
- char request_str[256]; |
- |
- XGetErrorText(dpy, error_event.error_code, error_str, sizeof(error_str)); |
- |
- strncpy(request_str, "Unknown", sizeof(request_str)); |
- if (error_event.request_code < 128) { |
- std::string num = base::UintToString(error_event.request_code); |
- XGetErrorDatabaseText( |
- dpy, "XRequest", num.c_str(), "Unknown", request_str, |
- sizeof(request_str)); |
- } else { |
- int num_ext; |
- char** ext_list = XListExtensions(dpy, &num_ext); |
- |
- for (int i = 0; i < num_ext; i++) { |
- int ext_code, first_event, first_error; |
- XQueryExtension(dpy, ext_list[i], &ext_code, &first_event, &first_error); |
- if (error_event.request_code == ext_code) { |
- std::string msg = StringPrintf( |
- "%s.%d", ext_list[i], error_event.minor_code); |
- XGetErrorDatabaseText( |
- dpy, "XRequest", msg.c_str(), "Unknown", request_str, |
- sizeof(request_str)); |
- break; |
- } |
- } |
- XFreeExtensionList(ext_list); |
- } |
- |
- LOG(ERROR) |
- << "X Error detected: " |
- << "serial " << error_event.serial << ", " |
- << "error_code " << static_cast<int>(error_event.error_code) |
- << " (" << error_str << "), " |
- << "request_code " << static_cast<int>(error_event.request_code) << ", " |
- << "minor_code " << static_cast<int>(error_event.minor_code) |
- << " (" << request_str << ")"; |
+ DCHECK(!MessageLoop::current() || |
+ MessageLoop::current()->type() == MessageLoop::TYPE_UI); |
+ DCHECK_EQ(dpy, error_event.display) |
+ << "Attempt to log error for mismatching X11 display."; |
+ LOG(ERROR) << BuildX11ErrorString(error_event); |
} |
// ---------------------------------------------------------------------------- |