Anuken/Mindustry

Crash on wayland

fgaz opened this issue ยท 38 comments

fgaz commented

Platform: Linux (with wayland)

Build: 102

Issue:

arc.backend.sdl.SDLError: wayland not available
	at arc.backend.sdl.SdlApplication.check(SdlApplication.java:181)
	at arc.backend.sdl.SdlApplication.init(SdlApplication.java:80)
	at arc.backend.sdl.SdlApplication.<init>(SdlApplication.java:30)
	at mindustry.desktop.DesktopLauncher.main(DesktopLauncher.java:46)

See NixOS/nixpkgs#72306 (review) for more info

Steps to reproduce:

  • Have wayland
  • Run Mindustry

Also set the environment variable SDL_VIDEODRIVER=wayland, with SDL_VIDEODRIVER=x11 this does not happen.

What fix do you propose? I don't use Wayland, and in fact this is my first time hearing about it. There's nothing in my use or compilation of SDL2 that should explicitly cause problems with Wayland.

fgaz commented

It might be that you are bundling an old sdl version? I see some binary blobs here in the arc package. (Maybe they aren't even used, I just skimmed through the repo)

It might be that you are bundling an old sdl version?

No, I'm using the latest version (2.0.10). Why do you need to use Wayland?

fgaz commented

No, I'm using the latest version (2.0.10)

Hmm, then by looking at https://bugzilla.libsdl.org/buglist.cgi?no_redirect=0&quicksearch=wayland+backend it may be the use of one of those functions, but this is just a guess.

Edit: nope, it seems to crash on SDL_Init, before any other call... weird

just use x, only useful thing wayland can do is let you rotate windows which is cool but nothing uses it

Why do you need to use Wayland?

I don't really use it that often. The main reason I opened this issue is because I'm the current maintainer of the NixOS' mindustry package, and the issue popped up during a review (see link in OP). So you'd have to ask the actual users, but I guess the usual reasons for Wayland vs X apply (I'm not gonna list them here, just search it on the web, there are a lot of resources).

Actually, as @petabyteboy mentioned, the issue only manifests when using SDL's Wayland backend (not default for now), so it's fairly low priority.

just use x, only useful thing wayland can do is let you rotate windows which is cool but nothing uses it

There are many advantages to wayland, like improved security, performance and power efficiency, and fixes to long-standing issues like screen tearing. Please research for a bit before making such a statement.

No, I'm using the latest version (2.0.10). Why do you need to use Wayland?

I don't need to use wayland, but it would be nice to be able to remove the Xwayland compatibility layer from my system at some point.

What fix do you propose? I don't use Wayland, and in fact this is my first time hearing about it. There's nothing in my use or compilation of SDL2 that should explicitly cause problems with Wayland.

I don't know the solution for now, but if you like you can assign this issue to me and I will take a closer look as I'm interested in improving wayland support in Mindustry.

I don't know the solution for now, but if you like you can assign this issue to me and I will take a closer look as I'm interested in improving wayland support in Mindustry.

Sure, but keep in mind that working on SDL issues through Java may be... difficult.

Closing due to inactivity.

Not sure if I should create a new issue. I guess that would depend on your personal preference.

Based on the discussion in the following thread: ValveSoftware/Dota-2#999
And the libSDL installation guide (https://wiki.libsdl.org/Installation)

SDL on Unix should only link against the C runtime (glibc). Every thing else it needs will be dynamically loaded at runtime: X11, ALSA, d-bus, etc. This means it is possible to build an SDL that has support for all sorts of targets built in, and it will examine the system at runtime to decide what should be used (for example, if Xlib isn't available, it might try to load Wayland support, etc). In that respect, if you plan to ship the SDL binary that you build, it is to your benefit to make sure your system has development headers for as many targets as possible, regardless of what you plan to personally use, so your final library is as robust as possible. See docs/README-linux.md for more details.

I would assume that all we need to do is provide an libSDL.so built with wayland support.

If you can point me to the correct spot to run Mindustry using another version of libSDL.so I'll gladly test that for you.

Replace libSDL2.so in the desktop.jar file (located in jre/desktop.jar).

Couldn't get it running using either static or dynamic loading of wayland modules. If I get to it I'll try writing a small c program to see if it works in general.

SDL with wayland works fine in general. I've used multiple SDL-based applications that "just worked", for example the fps game xonotic.

@petabyteboy I agree. What I'm not sure about is if the version I compiled works with wayland.

SDL in general seems to work. Playing sounds is no issue. I'm not able to create a window - but that is likely unrelated as we fail on init which in turn (assuming 1 to 1 mapping) works without error in c. (linked against either system, my version SDL or the one provided by arc.)

At this point I'm out of my depths. Not sure where to look next. Sorry =/

Replace libSDL2.so in the desktop.jar file (located in jre/desktop.jar).

Are you sure this file gets loaded? I can remove it from the jar file and the game still starts up (with Xorg). I think libsdl-arc64.so is the one that needs to be replaced.

The SDL shared library was needed at some point; that may not be the case anymore.

Recompiling arc64 may be difficult; I had to do a lot of fiddling around to get it working. The jnigen build file is located here; if you want to get a fresh copy of the shared library, clone Arc and run ./gradlew sdlnatives and look for the result here.

Thanks, I'm already experimenting with it. I was able to build a new libsdl-arc64 that dynamically links everything, but I could not start mindustry with it:

java.lang.UnsatisfiedLinkError: io.anuke.arc.backends.sdl.jni.SDL.SDL_WINDOWEVENT_SHOWN()I
	at io.anuke.arc.backends.sdl.jni.SDL.SDL_WINDOWEVENT_SHOWN(Native Method)
	at io.anuke.arc.backends.sdl.jni.SDL.<clinit>(SDL.java:124)
	at arc.backend.sdl.SdlApplication.lambda$init$0(SdlApplication.java:80)
	at arc.backend.sdl.SdlApplication.check(SdlApplication.java:180)
	at arc.backend.sdl.SdlApplication.init(SdlApplication.java:80)
	at arc.backend.sdl.SdlApplication.<init>(SdlApplication.java:30)
	at mindustry.desktop.DesktopLauncher.main(DesktopLauncher.java:46)
[E] Failed to save local crash report.: java.lang.NoClassDefFoundError: Could not initialize class io.anuke.arc.backends.sdl.jni.SDL
	at mindustry.desktop.DesktopLauncher.message(DesktopLauncher.java:310)
	at mindustry.desktop.DesktopLauncher.lambda$null$9(DesktopLauncher.java:199)
	at mindustry.desktop.DesktopLauncher.lambda$handleCrash$10(DesktopLauncher.java:199)
	at mindustry.net.CrashSender.send(CrashSender.java:72)
	at mindustry.desktop.DesktopLauncher.handleCrash(DesktopLauncher.java:196)
	at mindustry.desktop.DesktopLauncher.main(DesktopLauncher.java:56)

I will next try to build a static libSDL2 with wayland support (and then the jni binary), but this will need some more time.

Your version of Arc/Mindustry is outdated; pull from the repo.

Thanks, that was indeed an issue, I was using an old release jar as a base for my experiments, but built the natives from Arc master.

Now I can start the game using dynamically linked libraries from my distribution when the videodriver is x11. With the wayland videodriver it still fails. First I got a NullPointerException when initializing wayland, I had to add a line to print the full stacktrace:

java.lang.ExceptionInInitializerError
	at arc.backend.sdl.SdlGL20.glGetString(SdlGL20.java:88)
	at arc.backend.sdl.SdlGraphics.<init>(SdlGraphics.java:36)
	at arc.backend.sdl.SdlApplication.<init>(SdlApplication.java:35)
	at mindustry.desktop.DesktopLauncher.main(DesktopLauncher.java:46)
Caused by: arc.util.ArcRuntimeException: GLEW failed to initialize: Unknown error
	at arc.backend.sdl.jni.SDLGL.<clinit>(SDLGL.java:109)
	... 4 more
Exception in thread "main" java.lang.NullPointerException
	at mindustry.desktop.DesktopLauncher.lambda$handleCrash$8(DesktopLauncher.java:190)
	at mindustry.desktop.DesktopLauncher.handleCrash(DesktopLauncher.java:189)
	at mindustry.desktop.DesktopLauncher.main(DesktopLauncher.java:57)

That's definitely some progress!

The NullPointerException is irrelevant; it happens when the game fails to get some crash information. The real error seems to be GLEW failed to initialize: Unknown error. I don't know what causes this.

I've had issues with glew and wayland already. Namely blender archlinux and glew-wayland don't play nice atm. I didn't have time to follow it up but may help at this point:
:: glew and glew-wayland are in conflict. Remove glew-wayland?

There are some points of references on the subject. For example: nigels-com/glew#172

On my system (archlinux) there exist two package: glew and glew-wayland and trying to initialize glew results in just that error : CRITICAL: Failed to initialize GLEW: Unknown error which can be solved by installing glew-wayland.

I'm guessing libGLEW needs to be built against wayland and can't switch at runtime?

Oh I see, I will link it against a glew built with SYSTEM=linux-egl (that's the difference between the Arch packages glew and glew-wayland).

Aaaand: It works!

screenshot

(You can see that xeyes could not detect the mouse cursor once I moved it into the mindustry window)

Now let's talk about how we can make this work for everyone. There are several options:

  • The Mindustry project could provide a seperate build of mindustry.jar for wayland users with glew-wayland and a wayland-capable libSDL embedded into libsdl-arc64.so
  • Mindustry could ship with a dynamically linked build of libsdl-arc64.so. This would require linux users to installe the correct libraries and it could also create problems with different versions
  • For NixOS: We could build our own dynamically linked libsdl-arc64.so from a patched Arc source, but this would be relatively maintenance-heavy

For NixOS users I packaged something here:
https://github.com/petabyteboy/nixpkgs/tree/feature/mindustry-natives/pkgs/games/mindustry
The output contains two wrappers, bin/mindustry and bin/mindustry-wayland

My personal preference is to always link against system libraries. But you're right that might generate a lot of tickets due to system incompatibilities.

A nice solution would be different gradle build paths which allow static or dynamic linking?

For the jar release I would for the moment stay with static libraries until we've tested a bit more using dynamic linking.

Nice work @petabyteboy got it up and running on my system as well with the help of your patch!

I have no experience building with gradle thus I can not provide a full patch.
looking at backends/backend-sdl/src/test/java/NativesBuild.java I believe for linux shared builds the following should provide the necessary configurations:

lin64.cFlags = lin64.cFlags + " " + execCmd("pkg-config --cflags glew glu gl sdl2 openal");
lin64.cppFlags = lin64.cFlags;
lin64.linkerFlags = "-shared -m64" + " " + execCmd("pkg-config --libs glew glu gl sdl2 openal");
// used by? works without for me.
// lin64.libraries = execCmd("pkg-config --libs glew glu gl sdl2 openal");

In my experience pkg-config works on all modern system and there's no reason to provide these flags manually as they might change.
Also I believe when retrieving the flags this way "#include <SDL.h>" is the correct include in backends/backend-sdl/src/main/java/arc/backend/sdl/jni/SDL.java

@petabyteboy could you test that?

I had troubles with the configuration of the windows build path as well. So I commented these as well.

@Anuken Can we split windows and linux builds as well as static and dynamic link paths? I honestly would like to provide something more substantial but without understanding gradle it seems difficult :/

Can we split windows and linux builds?

Anuken/Arc@775feb6 makes builds only occur for the current platform by default - on Linux, only the Linux natives will be built, unless you specify -Pwindows when running Gradle.

static and dynamic link paths

What needs to be done in order for that to happen?

Thanks your new commits contain all the information I need, I'm preparing a PR.

When Anuken/Arc#15 is merged, the output binaries will be statically linked by default, but with gradle sdlnatives -Pdynamic dynamically linked binaries are produced for Linux.
I pushed a Nix derivation that makes use of this to my nixpkgs branch feature/mindustry-natives.

One final step would be an option to build a mindustry.jar with those dynamically linked binaries, no idea how to achieve that though.

Thanks @petabyteboy, now I don't have to switch to X for high-resolution mindustry anymore โ™ฅ

mse-k commented

close issue?

This issue should be closed now, I've tested with 2 different machines running on Wayland, with both the 104.6 build and the 105 alpha build.

Screenshot from 2020-09-16 23-36-15

Mostly an FYI, I still get this when running the flatpak package on archlinux in wayland without SDL_VIDEODRIVER=x11. However, I think this is an issue with the org.freedesktop.Platform runtime in flatpak.

However, I think this is an issue with the org.freedesktop.Platform runtime in flatpak.

Hmm, looking some more, maybe not. Could it be a problem with the flatpak package itself?

Aaand, I just tried running the 6.0 build 123.1 Jar from the release page directly with java, and still have this issue...

Looking at Anuken/Arc#15 maybe I have to create a custom build?

All we did here is linking against the system version of SDL instead of the static library provided with Arc.

I don't think this ever made it into the an official release and I don't think there's a runtime switch either. Meaning that yes you have to create a custom build.

I think we should wrap the mindustry/mindustry-wayland to set the SDL_VIDEODRIVER. Using the glew library at runtime with the SDL_VIDEODRIVER=wayland environment variable (as I have set it in my environment.variables) or using the glew-egl library with SDL_VIDEODRIVER=x11 can never work.

Meaning that yes you have to create a custom build.

Are there instruction on how to do so anywhere?

  • Clone https://github.com/Anuken/Arc
  • Ensure you have a recent gradle, jdk, SDL and so on in your environment, if on NixOS you can run nix-shell "<nixpkgs>" -A mindustry
  • Run gradle sdlnatives -Pdynamic

Possible workaround (summarizing information above). Copy .desktop file to ~/.local/applications

cp /usr/share/applications/mindustry.desktop ~/.local/share/applications

Replace Exec=mindustry with Exec=env SDL_VIDEODRIVER=x11 mindustry (Arch wiki)