From d3ae943330288b7c4fb8abed3fb167e52189e65e Mon Sep 17 00:00:00 2001 From: Simon McVittie <smcv@collabora.com> Date: Mon, 9 Aug 2021 12:42:29 +0100 Subject: [PATCH] pv-adverb: If we cannot regenerate ld.so.cache, fall back Before steamrt/steam-runtime-tools!338 (T14481), we relied on the LD_LIBRARY_PATH as our way to find libraries from the graphics stack provider (host system or Flatpak runtime), both /overrides/lib/MULTIARCH and /overrides/lib/MULTIARCH/aliases. However, this was not robust against games that (incorrectly) reset the LD_LIBRARY_PATH in their startup scripts, such as Dead Cells, Evoland Legendary Edition and Shenzhen I/O. Since !338, we maintain three separate library search paths: 1. The LD_LIBRARY_PATH that is used to run pv-adverb is the same as before. (This is getenv("LD_LIBRARY_PATH") in pv-adverb code.) 2. Library directories that contain libraries named by their SONAME (/overrides/lib/MULTIARCH) are prepended to ld.so.conf, after which we invoke ldconfig to regenerate ld.so.cache. This means games that reset the LD_LIBRARY_PATH will effectively still search /overrides/lib/MULTIARCH, as a result of the usual logic that reads ld.so.cache. (This is global_ld_so_conf_entries in pv-adverb code.) 3. Library directories that contain libraries not named by their SONAME (/overrides/lib/MULTIARCH/aliases) still need to be in the LD_LIBRARY_PATH, because ld.so.cache only lists libraries by their SONAMEs, so we still need to put these library directories in the LD_LIBRARY_PATH before invoking the actual game. (This is opt_set_ld_library_path in pv-adverb code.) This worked fine on systems like Debian 11 and Arch, but is unnecessarily fragile: if running ldconfig failed, there was no fallback, and the game would simply not launch correctly. In particular, ldconfig can fail to run on Ubuntu and old Debian systems (prior to Debian 9), as a result of a workaround involving /sbin/ldconfig being made a shell script wrapper around /sbin/ldconfig.real. We can mitigate this failure by falling back to the old (pre-!338) logic if ldconfig fails, with a warning. Games like Dead Cells will still not launch successfully in this mode, but better-behaved games (including most native Linux titles and all Proton titles) will survive. A subtlety here is that when we fall back, we need to find both /overrides/lib/MULTIARCH and /overrides/lib/MULTIARCH/aliases in the LD_LIBRARY_PATH; so we discard search paths 2 and 3, and keep using search path 1 for the actual game, not just pv-adverb. Signed-off-by: Simon McVittie <smcv@collabora.com> --- pressure-vessel/adverb.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pressure-vessel/adverb.c b/pressure-vessel/adverb.c index ac73b67d9..40c888036 100644 --- a/pressure-vessel/adverb.c +++ b/pressure-vessel/adverb.c @@ -1326,15 +1326,28 @@ main (int argc, if (opt_regenerate_ld_so_cache != NULL && opt_regenerate_ld_so_cache[0] != '\0') { - if (!regenerate_ld_so_cache (global_ld_so_conf_entries, opt_regenerate_ld_so_cache, - error)) + if (regenerate_ld_so_cache (global_ld_so_conf_entries, opt_regenerate_ld_so_cache, + error)) { - goto out; + g_debug ("Generated ld.so.cache in %s", opt_regenerate_ld_so_cache); + g_debug ("Setting LD_LIBARY_PATH to \"%s\"", opt_set_ld_library_path); + flatpak_bwrap_set_env (wrapped_command, "LD_LIBRARY_PATH", + opt_set_ld_library_path, TRUE); + } + else + { + /* If this fails, it is not fatal - carry on anyway. However, + * we must not use opt_set_ld_library_path in this case, because + * in the case where we're not regenerating the ld.so.cache, + * we have to rely on the longer LD_LIBRARY_PATH with which we + * were invoked, which includes the library paths that were in + * global_ld_so_conf_entries. */ + g_warning ("%s", local_error->message); + g_warning ("Recovering by keeping our previous LD_LIBRARY_PATH"); + g_clear_error (error); } - g_debug ("Generated ld.so.cache in %s", opt_regenerate_ld_so_cache); } - - if (opt_set_ld_library_path != NULL) + else if (opt_set_ld_library_path != NULL) { g_debug ("Setting LD_LIBARY_PATH to \"%s\"", opt_set_ld_library_path); flatpak_bwrap_set_env (wrapped_command, "LD_LIBRARY_PATH", -- GitLab