We received a report that Tor Browser 11.0 now fails to start on a (Gentoo) Linux machine that does not have Wayland installed. Firefox 91.3.0esr does start.
looks like the relevant logic is in WidgetUtilsGtk.cpp
I suspect someone is going to have to do some debugging in an actual Gentoo environment to figure out what's going on; the only way the user can get down the described path is if this boy returns true:
bool GdkIsWaylandDisplay(GdkDisplay* display) { static auto sGdkWaylandDisplayGetType = // a gdk function for returning a 'type' object (contains RTTI) for wayland displays (GType(*)())dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_type"); return sGdkWaylandDisplayGetType && // compares the default display's type (aka the display returned by gdk_display_get_default()) with a wayland display's type G_TYPE_CHECK_INSTANCE_TYPE(display, sGdkWaylandDisplayGetType());}
eg the only way this returns true is if the default display's type matches the reported type of a wayland display.
This also occurs on Slackware 14.2, and will occur on any (generally, older, or less conventional) Linux distribution that does not ship with Wayland shared libraries as a built option.
Linking to the shared library that provides gdk_wayland_display_get_wl_compositor is a compile time dependency. Guarding it with (runtime) code does not solve the issue as the library is searched for on ELF load, not during execution. This is why it is guarded with the preprocessor #define MOZ_GTK_WAYLAND, which in turn is guarded by MOZ_WAYLAND, which is a configure option. Presumably this has been recently turned on by default due to the newer Firefox.
This is the issue with shipping a single binary to multiple Linux distributions, and also why they each mostly have their own package management systems that are only barely compatible. With one binary you need to design your shared library use for the lowest common denominator. Distributions generally work with you here by shipping multiple major versions of libraries and being somewhat aware of the "consensus" around what shared libraries other distros are using, but every so often there will be a substantial or controversial architectural change that will be adopted at different rates and you will have these issues.
There are 5 solutions, in order of simplest and least featureful first:
Simply do not support distros that do not support Wayland (current method)
Disable MOZ_WAYLAND "for now" (essentially, the opposite of the first option)- Slackware at least is nearing release (as much as one can say that about a "when it's ready" distro) of its next major version which supplies Wayland and its libraries, and Gentoo at least makes it an option
Provide different builds, one with and one without
Change the Mozilla source to statically link to Wayland's libraries (generally fairly to extremely fraught)
Change the Mozilla source to not link to Wayland's shared library and instead use dlopen to attempt to dynamically load it if the quoted runtime check passes.
I would supply an example of the last option but I haven't yet found the documentation on how to build Tor Browser on my Slackware 14.2 machine as it seems to be caught in transit between documentation servers...
I should note that "not supporting" distros that don't support Wayland themselves isn't strictly accurate as they could rebuild Tor Browser themselves, but presumably there are many reasons why the Tor Project supplies a binary, not least of which is retaining control of updatability.
Amazing what not looking at an issue tired will do for you. Looking at the code again, @bdavis40 is correct, we must be linking in this symbol because MOZ_WAYLAND is defined (which of course would cause a symbol issue). That said, Mozilla's esr91.3's libxul.so also lists gdk_wayland_display_get_wl_compositor as an undefined symbol same as tor-browser's libxul.so:
$ nm -D libxul.so | grep gdk_wayland_display_get_wl_compositor U gdk_wayland_display_get_wl_compositor
So I don't quite understand how they manage to ship 1 binary that works on both types of systems...
There must be a difference here in how we're consuming/linking against the gtk libraries vs how official firefox builds do. In the windows world you can force symbols to 'delay load' whereby symbols are getprocaddress'd (seems roughly equivalent to dlsym?) at runtime rather than causing a load/init-time failure.
Haha yes that will do it! I know Slackware builds their own from source (without MOZ_WAYLAND) but clearly that doesn't apply to Gentoo because it shows the undefined symbol.
I'm really not familiar with the linking in gtk nor Tor Browser nor Firefox builds; maybe there is another way that official Firefox builds use to get around it. But yes, that's my understanding of getprocaddress vs dlsym too.
Haha yes that will do it! I know Slackware builds their own from source (without MOZ_WAYLAND) but clearly that doesn't apply to Gentoo because it shows the undefined symbol.
I'm really not familiar with the linking in gtk nor Tor Browser nor Firefox builds; maybe there is another way that official Firefox builds use to get around it. But yes, that's my understanding of getprocaddress vs dlsym too.
Is the official Firefox build from Mozilla not affected by this issue?
Correct, official Mozilla build is not affected. I just downloaded and tested firefox-91.4.0esr and firefox-95.0 from Mozilla.
I suspect there are other linking differences between Mozilla and Tor Project builds too. The below complaints about GLIBCXX do not appear in the Mozilla 91 ESR build, but NSS ones do.
./libxul.so: /usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.26' not found (required by ./libxul.so)./libxul.so: /usr/lib64/libstdc++.so.6: version 'GLIBCXX_3.4.22' not found (required by ./libxul.so)
Saved it as shim.c, then ran cc -shared -o shim.so shim.c.
Then edited ~/.local/share/applications/start-tor-browser.desktop to prepend the following to the Exec= field: env LD_PRELOAD=/path/to/shim.so. This of course might crash the application when ran within an actual wayland environment, but is fine for my purposes.
This also works for me, thanks! Clever solution. On my machine, the script that updates the paths in the .desktop file also removes the added env LDPRELOAD once it's executed, but it works for one launch, at least.