summaryrefslogtreecommitdiffstats
path: root/platform/linuxbsd/x11/display_server_x11.cpp
diff options
context:
space:
mode:
authornee <nee-git@patchouli.garden>2023-03-19 13:54:24 +0100
committernee <nee-git@patchouli.garden>2023-06-05 17:28:21 +0200
commitb13c82e964ec2e38d182fdcf5f2d6208a1b8f1a9 (patch)
tree1ae8d85cfdb908187420f3978c95f095de87ebe2 /platform/linuxbsd/x11/display_server_x11.cpp
parente5cc494fbf4f5564c16d3deadb3a83a3c58b7546 (diff)
downloadredot-engine-b13c82e964ec2e38d182fdcf5f2d6208a1b8f1a9.tar.gz
[Linux/X11] Add a default error handler for X11 to avoid crashes.
The default behaviour for X11 is to crash even on non-fatal errors when there is no error handler set. This change allows the window to stay open and may enable users to save their work when things go wrong. This acts as a workaround for #65425 and #68471
Diffstat (limited to 'platform/linuxbsd/x11/display_server_x11.cpp')
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp21
1 files changed, 20 insertions, 1 deletions
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index e5f278cc19..552c15bf01 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -821,12 +821,30 @@ Size2i DisplayServerX11::screen_get_size(int p_screen) const {
return _screen_get_rect(p_screen).size;
}
+// A Handler to avoid crashing on non-fatal X errors by default.
+//
+// The original X11 error formatter `_XPrintDefaultError` is defined here:
+// https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/e45ca7b41dcd3ace7681d6897505f85d374640f2/src/XlibInt.c#L1322
+// It is not exposed through the API, accesses X11 internals,
+// and is much more complex, so this is a less complete simplified error X11 printer.
+int default_window_error_handler(Display *display, XErrorEvent *error) {
+ static char message[1024];
+ XGetErrorText(display, error->error_code, message, sizeof(message));
+
+ ERR_PRINT(vformat("Unhandled XServer error: %s"
+ "\n Major opcode of failed request: %d"
+ "\n Serial number of failed request: %d"
+ "\n Current serial number in output stream: %d",
+ String::utf8(message), error->request_code, error->minor_code, error->serial));
+ return 0;
+}
+
bool g_bad_window = false;
int bad_window_error_handler(Display *display, XErrorEvent *error) {
if (error->error_code == BadWindow) {
g_bad_window = true;
} else {
- ERR_PRINT("Unhandled XServer error code: " + itos(error->error_code));
+ return default_window_error_handler(display, error);
}
return 0;
}
@@ -5746,6 +5764,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
portal_desktop = memnew(FreeDesktopPortalDesktop);
#endif
+ XSetErrorHandler(&default_window_error_handler);
r_error = OK;
}