| 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);
|
| }
|
|
|
| // ----------------------------------------------------------------------------
|
|
|