ValveSoftware / steam-runtime

A runtime environment for Steam applications
Other
1.17k stars 86 forks source link

Jack client library is incompatible with system's implementation, breaking jack-based configurations #438

Open mittorn opened 2 years ago

mittorn commented 2 years ago

Your system information

alsa-jack setups does not work too because of missing asound.conf (already reported)

Steps for reproducing this issue:

  1. Install jack legacy version (not jack2)
  2. setup alsa-jack in asound.conf
  3. Enjoy no sound in steam runtime
kisak-valve commented 2 years ago

Possible duplicate of #307.

smcv commented 2 years ago

This is https://github.com/ValveSoftware/steam-runtime/blob/master/doc/steamlinuxruntime-known-issues.md#audio.

Unfortunately the protocol between the JACK server and the JACK client library is private to a particular version (and there are at least two common implementations, jackd2 and legacy), so the runtime cannot include a matching version for any particular distribution: each distribution would require a different version. This is unlike Pulseaudio and Pipewire, where the protocol between server and client is backwards- and forwards-compatible, so we can use the runtime's client library to talk to the host's server.

The current recommendation is to use either Pulseaudio or Pipewire to get audio between games and the host. These work via a backwards- and forwards-compatible protocol that is very suitable for crossing container boundaries.

Importing the host JACK client library like we do for OpenGL and Vulkan ICDs would be possible in principle if it is at least as new as the one that the runtime would normally have included; but the more libraries we do this with, the less stable the overall system is, and the less likely it is that games that need the container runtime will work (for anyone, not just JACK users).

Importing the host JACK client library alone is not enough: for each of its recursive dependencies, we would also have to identify whether the dependency is newer on the host or in the container, and if the host version is newer, import that too (as we do for dependencies of OpenGL and Vulkan ICDs). If Debian is typical, then this means libsamplerate.so.0 for jackd2, and libdb-5.3.so for legacy JACK. Again, the more we do this, the more likely it is that we will hit one of the corner-cases that break games entirely.

If the host JACK client library is older than the one that the container runtime (in the soldier runtime this means jackd2 1.9.12~dfsg-2, from Debian 10), then it will not necessarily export all the symbols that are required by dependent executables and libraries in the runtime environment, potentially making it impossible to load those executables and libraries at all. We can get away with this for OpenGL because OpenGL applications are expected to use dlsym()-based techniques for nearly all symbols, and we can get away with this for Vulkan because we are careful to keep using the container's version of the Vulkan-Loader library if the host's is older; but the same does not seem to be viable for JACK.

Sorry, the design of JACK just isn't very app-container-friendly. Flatpak apps encounter the same problems.

smcv commented 2 years ago

To be clear, the problem here is not really that the JACK server is broken in the runtime container: the JACK server doesn't run in the runtime container at all. It's more like "JACK client library in runtime container is incompatible with JACK server on host".

In basically all client-server protocols (not just JACK but also X11, Wayland, D-Bus, Pulseaudio, Pipewire, etc.), what we get is a client library in the runtime container, talking to a server outside the container. In most of those client-server protocols, the protocol is designed to be cross-version compatible, with graceful degradation to lowest-common-denominator functionality (so if you have either a Pulseaudio 10 client talking to a Pulseaudio 15 server or a Pulseaudio 15 client talking to a Pulseaudio 10 server, it'll use the Pulseaudio 10 protocol). The difference for JACK is that its protocol doesn't work that way.

mittorn commented 2 years ago

Yes, i mean jack-based configurations are broken. Jack has stable API/ABI, but not protocol (even replacing jack1 by jack2 does not break any installed software) Other issue that jack (especcially, jack1) client library is depended on libdb-5.3 symbol versions, so contatiner system should determine which libdb version to use (using newer version should work) But why even jack library placed to container?

Maybe just provide global configuration that allow override container libraries? Now i forced to replace container files. I always can install newer library version to system, so container updates will not break anything

smcv commented 2 years ago

But why even jack library placed to container?

The container runtime takes libraries from an ordinary Linux distribution (Steam Runtime 2 'soldier' is based on Debian 10) and we have to either include all of those libraries' dependencies, or recompile them with features like JACK disabled.

In this case it seems to be libasound2-plugins (part of alsa-libs) that depends on a JACK client library implementation. We could recompile alsa-libs with the JACK plugin disabled, but then you definitely wouldn't be able to get audio via JACK...

Maybe just provide global configuration that allow override container libraries?

Sorry, we cannot support all the possible ways that people can modify the container. The entire point of this container is to get a more predictable runtime environment.

Now i forced to replace container files

We cannot support this. Any modification is at your own risk.

I always can install newer library version to system, so container updates will not break anything

Maybe you can, but not everyone is using a rolling-release host system with everything constantly at the newest version.

smcv commented 2 years ago

Other issue that jack (especcially, jack1) client library is depended on libdb-5.3 symbol versions, so contatiner system should determine which libdb version to use (using newer version should work)

This looks like a significant problem for the jackd 1 client library specifically (not an issue for the jackd2 client library as far as I can see), because libdb is a weird library for historical reasons. It doesn't use the usual libfoo.so.MAJOR -> libfoo.so.MAJOR.MINOR symlink, which defeats the mechanism we usually use to detect which one of a pair of libraries is newer; and versioned symbols seem to be patched in on a per-distribution basis rather than being part of upstream code, so the libdb-5.3.so from the host system is not necessarily compatible with the one in the container, even if the one on the host system is newer.

We need a copy of libdb-5.3.so in the container for the Python standard library, not just for JACK, so we can't resolve this by removing the one from the container; but we also can't have both the host copy and the container copy, we have to choose one, somehow. If it isn't possible to choose a copy of libdb-5.3.so that is compatible with both the JACK client library and Python, then it will be impossible to do the right thing, because there is no right thing we can do.

mittorn commented 2 years ago

libdb is not backward-compatible? Is it possinble use newest version by comparing it with host's one? Now i switched to jack2 and it seems only need jack libraries from host, not libdb. Even if libdb incompatible, jack is loaded dynamicly and broken jack library does not prevent applications from running (except of apps using jack directly) As jack is not used by usual users, why not make some simple overrde option? I spend half-a-day to make it work (and 5 minutes for legacy runtime) because of complex container structure and not found any solution in documentation. If there was documented way to force system libraries in container, i spent 5-10 minutes. not few hours to it. Wine has documented library overrides, why steam runtime can't have something similar?

OdinVex commented 4 months ago

*out of breath* Ah, so this is what is preventing it. I've been trying to get this working for days now. Spoot.