Why could XGetDefault("Xft", "antialias") crash in GTK app?

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Why could XGetDefault("Xft", "antialias") crash in GTK app?

Postby VadZ » Wed Oct 18, 2023 7:18 pm

Sorry for such a weird question, but I've discovered that my application using CEF (and GTK) crashes on startup under Ubuntu 22.04 even though it works perfectly fine under Debian 12. Debugging the crash shows that it happens because, after initializing successfully, the main window gets repainted and while handling the "repaint" event GTK uses Pango which uses Cairo which ends up calling XGetDefault("Xft", "antialias") which crashes due to trying to lock a null mutex.

And I can reproduce the problem simply by calling XGetDefault() with these parameters myself during the application startup, but the "funny" thing is that this call works perfectly fine just before CefInitialize() but crashes if it's called immediately after it.

My only idea is that this is somehow related to the fact that I need to do the equivalent of LD_PRELOAD=libcef.so (i.e. I need to either just do exactly this or put it as the very first library on the linker command line with -Wl,--no-as-needed before it, as it's actually not referenced by the executable itself, but only by another shared library used by it), and so some "wrong" function gets somehow called, but I can't avoid doing this as otherwise CEF doesn't work at all and, anyhow, I don't really see how could it result in this problem, so maybe this idea is completely wrong.

Searching the web for "XGetDefault" and "XrmQGetResource" (which is the function called from it that actually crashes) I can see that others ran into this problem before, in several different applications using CEF or in Chrome itself, but there is never any explanation for it. If anybody has any idea about what could be going on here and any suggestions for how to fix, or work around, this problem, I'd be very grateful!
VadZ
Techie
 
Posts: 16
Joined: Wed Oct 18, 2023 7:02 pm

Re: Why could XGetDefault("Xft", "antialias") crash in GTK a

Postby VadZ » Thu Oct 19, 2023 7:03 pm

BTW, this can be reproduced in the cefsimple test with just the following trivial patch:
Code: Select all
diff --git a/tests/cefsimple/cefsimple_linux.cc b/tests/cefsimple/cefsimple_linux.cc
index 26b3c7b91..a1e9ad512 100644
--- a/tests/cefsimple/cefsimple_linux.cc
+++ b/tests/cefsimple/cefsimple_linux.cc
@@ -72,6 +72,13 @@ int main(int argc, char* argv[]) {
   settings.no_sandbox = true;
 #endif
 
+  auto dpy = ::XOpenDisplay(":0");
+  if (!dpy) {
+      fprintf(stderr, "XOpenDisplay() failed.\n");
+      return 1;
+  }
+  fprintf(stderr, R"(Before CefInitialize: XGetDefault("Xft", "antialias") = "%s")" "\n", XGetDefault(dpy, "Xft", "antialias"));
+
   // SimpleApp implements application-level callbacks for the browser process.
   // It will create the first browser instance in OnContextInitialized() after
   // CEF has initialized.
@@ -80,6 +87,8 @@ int main(int argc, char* argv[]) {
   // Initialize CEF for the browser process.
   CefInitialize(main_args, settings, app.get(), nullptr);
 
+  fprintf(stderr, R"(After CefInitialize: XGetDefault("Xft", "antialias") = "%s")" "\n", XGetDefault(dpy, "Xft", "antialias"));
+
   // Run the CEF message loop. This will block until CefQuitMessageLoop() is
   // called.
   CefRunMessageLoop();


The output is:

Code: Select all
$ ./cefsimple --url=chrome://about                       
Before CefInitialize: XGetDefault("Xft", "antialias") = "1"
[1020/020228.354683:WARNING:chrome_browser_cloud_management_controller.cc(88)] Could not create policy manager as CBCM is not enabled.
[1]    59260 segmentation fault (core dumped)  ./cefsimple --url=chrome://about
VadZ
Techie
 
Posts: 16
Joined: Wed Oct 18, 2023 7:02 pm

Re: Why could XGetDefault("Xft", "antialias") crash in GTK a

Postby VadZ » Thu Oct 19, 2023 8:33 pm

And I finally found the answer which is, of course, embarrassingly trivial in hindsight: Chrome calls XInitThreads() during its initialization, which makes X11 use mutex fields, but any structs allocated before XInitThreads() can't be used after it is called, so the application using CEF must call it itself as early as possible.

The extra nasty thing is that the libX11.so version shipped with Debian 12 does this automatically on its own from a global initialization function, because this was changed in v1.8.4 of libX11 (who knew this 40 year old library could still change in backwards incompatible ways?), as explained in their change log (https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/README.md?plain=1#L68-L73), while Ubuntu 22.04 uses 1.7.5 predating it.
VadZ
Techie
 
Posts: 16
Joined: Wed Oct 18, 2023 7:02 pm


Return to Support Forum

Who is online

Users browsing this forum: Google [Bot] and 216 guests