Commit 9e18a4aa authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

Reland "Set Xlib error handler after GTK X11 initialization"

This is a reland of 2ed82a41

Original change's description:
> Set Xlib error handler after GTK X11 initialization
>
> The default GTK error handler exits the process, which we don't want.
> We used to reset the error handler at some point after GTK
> initialization, but this became lost after r815319.
>
> Also refactor the XlibLoader instance to be global so it doesn't have
> to be created multiple times for each connection.
>
> R=sky
>
> Bug: 1145929
> Change-Id: I73a3f27551534c2262bd8994d33e30fc2a0a4e27
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2527743
> Commit-Queue: Thomas Anderson <thomasanderson@chromium.org>
> Reviewed-by: Scott Violet <sky@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#825585}

Bug: 1145929
Change-Id: Ib65f3add91181b3bf82dd71f7b9b87a9a681a53d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2533199
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Cr-Commit-Position: refs/heads/master@{#826572}
parent b78a1594
...@@ -189,8 +189,7 @@ XlibDisplayWrapper Connection::GetXlibDisplay(XlibDisplayType type) { ...@@ -189,8 +189,7 @@ XlibDisplayWrapper Connection::GetXlibDisplay(XlibDisplayType type) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!xlib_display_) if (!xlib_display_)
xlib_display_ = base::WrapUnique(new XlibDisplay(display_string_)); xlib_display_ = base::WrapUnique(new XlibDisplay(display_string_));
return XlibDisplayWrapper(xlib_display_->xlib_loader_.get(), return XlibDisplayWrapper(xlib_display_->display_, type);
xlib_display_->display_, type);
} }
Connection::Request::Request(unsigned int sequence, Connection::Request::Request(unsigned int sequence,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/check.h" #include "base/check.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/no_destructor.h"
#include "library_loaders/xlib_loader.h" #include "library_loaders/xlib_loader.h"
namespace x11 { namespace x11 {
...@@ -18,41 +19,58 @@ int XlibErrorHandler(void*, void*) { ...@@ -18,41 +19,58 @@ int XlibErrorHandler(void*, void*) {
return 0; return 0;
} }
XlibLoader* GetXlibLoader() {
static base::NoDestructor<XlibLoader> xlib_loader;
return xlib_loader.get();
}
} // namespace } // namespace
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
XlibDisplay::XlibDisplay(const std::string& address) { void InitXlib() {
xlib_loader_ = std::make_unique<XlibLoader>(); auto* xlib_loader = GetXlibLoader();
CHECK(xlib_loader_->Load("libX11.so.6")); if (xlib_loader->loaded())
return;
CHECK(xlib_loader->Load("libX11.so.6"));
CHECK(xlib_loader_->XInitThreads()); CHECK(xlib_loader->XInitThreads());
// The default Xlib error handler calls exit(1), which we don't want. This // The default Xlib error handler calls exit(1), which we don't want. This
// shouldn't happen in the browser process since only XProto requests are // shouldn't happen in the browser process since only XProto requests are
// made, but in the GPU process, GLX can make Xlib requests, so setting an // made, but in the GPU process, GLX can make Xlib requests, so setting an
// error handler is necessary. Importantly, there's also an IO error handler, // error handler is necessary. Importantly, there's also an IO error handler,
// and Xlib always calls exit(1) with no way to change this behavior. // and Xlib always calls exit(1) with no way to change this behavior.
xlib_loader_->XSetErrorHandler(XlibErrorHandler); SetXlibErrorHandler();
}
DISABLE_CFI_ICALL
void SetXlibErrorHandler() {
GetXlibLoader()->XSetErrorHandler(XlibErrorHandler);
}
DISABLE_CFI_ICALL
XlibDisplay::XlibDisplay(const std::string& address) {
InitXlib();
display_ = display_ = GetXlibLoader()->XOpenDisplay(address.empty() ? nullptr
xlib_loader_->XOpenDisplay(address.empty() ? nullptr : address.c_str()); : address.c_str());
} }
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
XlibDisplay::~XlibDisplay() { XlibDisplay::~XlibDisplay() {
if (display_) if (display_)
xlib_loader_->XCloseDisplay(display_); GetXlibLoader()->XCloseDisplay(display_);
} }
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
XlibDisplayWrapper::XlibDisplayWrapper(XlibLoader* xlib_loader, XlibDisplayWrapper::XlibDisplayWrapper(struct _XDisplay* display,
struct _XDisplay* display,
XlibDisplayType type) XlibDisplayType type)
: xlib_loader_(xlib_loader), display_(display), type_(type) { : display_(display), type_(type) {
if (!display_) if (!display_)
return; return;
if (type == XlibDisplayType::kSyncing) if (type == XlibDisplayType::kSyncing)
xlib_loader_->XSynchronize(display_, true); GetXlibLoader()->XSynchronize(display_, true);
} }
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
...@@ -60,25 +78,21 @@ XlibDisplayWrapper::~XlibDisplayWrapper() { ...@@ -60,25 +78,21 @@ XlibDisplayWrapper::~XlibDisplayWrapper() {
if (!display_) if (!display_)
return; return;
if (type_ == XlibDisplayType::kFlushing) if (type_ == XlibDisplayType::kFlushing)
xlib_loader_->XFlush(display_); GetXlibLoader()->XFlush(display_);
else if (type_ == XlibDisplayType::kSyncing) else if (type_ == XlibDisplayType::kSyncing)
xlib_loader_->XSynchronize(display_, false); GetXlibLoader()->XSynchronize(display_, false);
} }
XlibDisplayWrapper::XlibDisplayWrapper(XlibDisplayWrapper&& other) { XlibDisplayWrapper::XlibDisplayWrapper(XlibDisplayWrapper&& other) {
xlib_loader_ = other.xlib_loader_;
display_ = other.display_; display_ = other.display_;
type_ = other.type_; type_ = other.type_;
other.xlib_loader_ = nullptr;
other.display_ = nullptr; other.display_ = nullptr;
other.type_ = XlibDisplayType::kNormal; other.type_ = XlibDisplayType::kNormal;
} }
XlibDisplayWrapper& XlibDisplayWrapper::operator=(XlibDisplayWrapper&& other) { XlibDisplayWrapper& XlibDisplayWrapper::operator=(XlibDisplayWrapper&& other) {
xlib_loader_ = other.xlib_loader_;
display_ = other.display_; display_ = other.display_;
type_ = other.type_; type_ = other.type_;
other.xlib_loader_ = nullptr;
other.display_ = nullptr; other.display_ = nullptr;
other.type_ = XlibDisplayType::kNormal; other.type_ = XlibDisplayType::kNormal;
return *this; return *this;
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
#include "base/component_export.h" #include "base/component_export.h"
struct _XDisplay; struct _XDisplay;
class XlibLoader;
namespace x11 { namespace x11 {
...@@ -26,6 +25,12 @@ enum class XlibDisplayType { ...@@ -26,6 +25,12 @@ enum class XlibDisplayType {
kSyncing, kSyncing,
}; };
// Loads Xlib, initializes threads, and sets a default error handler.
COMPONENT_EXPORT(X11) void InitXlib();
// Sets an async error handler which only logs an error message.
COMPONENT_EXPORT(X11) void SetXlibErrorHandler();
// A scoped Xlib display. // A scoped Xlib display.
class COMPONENT_EXPORT(X11) XlibDisplay { class COMPONENT_EXPORT(X11) XlibDisplay {
public: public:
...@@ -38,7 +43,6 @@ class COMPONENT_EXPORT(X11) XlibDisplay { ...@@ -38,7 +43,6 @@ class COMPONENT_EXPORT(X11) XlibDisplay {
explicit XlibDisplay(const std::string& address); explicit XlibDisplay(const std::string& address);
struct _XDisplay* display_ = nullptr; struct _XDisplay* display_ = nullptr;
std::unique_ptr<XlibLoader> xlib_loader_;
}; };
// A temporary wrapper around an unowned Xlib display that adds behavior // A temporary wrapper around an unowned Xlib display that adds behavior
...@@ -56,13 +60,10 @@ class COMPONENT_EXPORT(X11) XlibDisplayWrapper { ...@@ -56,13 +60,10 @@ class COMPONENT_EXPORT(X11) XlibDisplayWrapper {
XlibDisplayWrapper& operator=(XlibDisplayWrapper&& other); XlibDisplayWrapper& operator=(XlibDisplayWrapper&& other);
private: private:
XlibDisplayWrapper(XlibLoader* xlib_loader, XlibDisplayWrapper(struct _XDisplay* display, XlibDisplayType type);
struct _XDisplay* display,
XlibDisplayType type);
friend class Connection; friend class Connection;
XlibLoader* xlib_loader_;
struct _XDisplay* display_; struct _XDisplay* display_;
XlibDisplayType type_; XlibDisplayType type_;
}; };
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ui/base/x/x11_util.h" #include "ui/base/x/x11_util.h"
#include "ui/events/platform/x11/x11_event_source.h" #include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "ui/gfx/x/xlib_support.h"
#include "ui/gfx/x/xproto.h" #include "ui/gfx/x/xproto.h"
#include "ui/gtk/x/gtk_event_loop_x11.h" #include "ui/gtk/x/gtk_event_loop_x11.h"
#include "ui/platform_window/x11/x11_window.h" #include "ui/platform_window/x11/x11_window.h"
...@@ -31,6 +32,7 @@ GtkUiDelegateX11::GtkUiDelegateX11(x11::Connection* connection) ...@@ -31,6 +32,7 @@ GtkUiDelegateX11::GtkUiDelegateX11(x11::Connection* connection)
: connection_(connection) { : connection_(connection) {
DCHECK(connection_); DCHECK(connection_);
gdk_set_allowed_backends("x11"); gdk_set_allowed_backends("x11");
x11::InitXlib();
} }
GtkUiDelegateX11::~GtkUiDelegateX11() = default; GtkUiDelegateX11::~GtkUiDelegateX11() = default;
...@@ -38,6 +40,11 @@ GtkUiDelegateX11::~GtkUiDelegateX11() = default; ...@@ -38,6 +40,11 @@ GtkUiDelegateX11::~GtkUiDelegateX11() = default;
void GtkUiDelegateX11::OnInitialized() { void GtkUiDelegateX11::OnInitialized() {
// Ensure the singleton instance of GtkEventLoopX11 is created and started. // Ensure the singleton instance of GtkEventLoopX11 is created and started.
GtkEventLoopX11::EnsureInstance(); GtkEventLoopX11::EnsureInstance();
// GTK sets an Xlib error handler that exits the process on any async errors.
// We don't want this behavior, so reset the error handler to something that
// just logs the error.
x11::SetXlibErrorHandler();
} }
GdkKeymap* GtkUiDelegateX11::GetGdkKeymap() { GdkKeymap* GtkUiDelegateX11::GetGdkKeymap() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment