From 4d9a5d4b507d009e0f7ce0e40aa90d51256b8700 Mon Sep 17 00:00:00 2001 From: lucannez64 <58551020+lucannez64@users.noreply.github.com> Date: Sun, 18 Oct 2026 15:10:04 +0200 Subject: [PATCH 1/6] fix(launcher): disable inherited MangoHud fdinfo scans --- docs/TROUBLESHOOTING.md | 33 ++++++++++++++++++++++++++++ tools/riot-launcher-offline-check.py | 16 +++++++++++--- tools/run-riot-client.sh | 5 +++++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 7d8b3f4..14515f8 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -422,3 +422,36 @@ Recovery requires every matching client to be at least 60 seconds old and a complete Hyprland window record (`class`, `title`, `mapped`, `hidden`). A second process scan after window inspection must find the same client identities and no game. Missing information or shutdown failure leaves normal launch in charge. + +## Installer aborts on `/proc//fdinfo` + +[Issue #38](https://github.com/lucannez64/darling-lol/issues/38) reports an +uncaught `ghc::filesystem::filesystem_error` with `Permission denied` on +`/proc//fdinfo`. `ghc::filesystem` is a C++ filesystem library, not evidence +that the Riot installer is written in Haskell. + +An independent guest/native Vulkan probe reproduced this exact exception with +MangoHud 0.8.4 enabled on 2026-10-18. MangoHud's `GPU_fdinfo::find_fd()` builds +`/proc//fdinfo` and uses a throwing directory iterator. Inside Darling, +the native library's PID is in the guest PID namespace while its native `/proc` +view can still refer to host processes: the probe's native PID 35 resolved to an +inaccessible host process. The same probe completed Vulkan instance, device and +swapchain creation with MangoHud disabled. This does not establish the cause of +every installer abort; confirmation from the original reporter remains pending. + +The normal launcher now unsets `MANGOHUD` and exports `DISABLE_MANGOHUD=1` before +runtime helpers start, including first-time installation. This disables inherited +implicit MangoHud activation for the launched session without changing the host +configuration. Do not wrap the launcher in `mangohud` or explicitly force its +Vulkan layer. Updating these launcher scripts needs no Darling rebuild. For an +older checkout, use: + +```sh +env -u MANGOHUD DISABLE_MANGOHUD=1 ./scripts/installer.sh euw +``` + +Do not run the installer as root or change `/proc` permissions. If it still +fails, include the exception and whether a host overlay was enabled; redact +account tokens from logs. + +Upstream source: [MangoHud 0.8.4 fdinfo scan](https://github.com/flightlessmango/MangoHud/blob/v0.8.4/src/gpu_fdinfo.cpp#L9). diff --git a/tools/riot-launcher-offline-check.py b/tools/riot-launcher-offline-check.py index 1254b7a..1d661e7 100644 --- a/tools/riot-launcher-offline-check.py +++ b/tools/riot-launcher-offline-check.py @@ -22,9 +22,9 @@ def check(): stub = f'''#!{sys.executable} import json, os, sys record = {{"command": os.path.basename(sys.argv[0]), "args": sys.argv[1:]}} -if record["command"] == "darling": +if record["command"] in ("darling", "python3"): record["flags"] = {{key: os.environ.get(key) for key in - ("RCLOL_APP_ARG3", "RCLOL_APP_ARG3_SLOT", "RCLOL_UX_ARG2", "RCLOL_UX_ARG2_SLOT", "RCLOL_UX_ARG1", "RCLOL_APP_ARGS", "RCLOL_APP_ARG2", "DYLD_INSERT_LIBRARIES", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH", "DARLING_XSHM_LIBRARY")}} + ("RCLOL_APP_ARG3", "RCLOL_APP_ARG3_SLOT", "RCLOL_UX_ARG2", "RCLOL_UX_ARG2_SLOT", "RCLOL_UX_ARG1", "RCLOL_APP_ARGS", "RCLOL_APP_ARG2", "DYLD_INSERT_LIBRARIES", "DYLD_LIBRARY_PATH", "DYLD_FRAMEWORK_PATH", "DARLING_XSHM_LIBRARY", "MANGOHUD", "DISABLE_MANGOHUD")}} with open({str(log)!r}, "a") as output: output.write(json.dumps(record) + "\\n") ''' @@ -46,6 +46,8 @@ with open({str(log)!r}, "a") as output: env["DYLD_INSERT_LIBRARIES"] = "/Users/offline-check/zzlogdir.dylib:/tmp/inherited.dylib" env["RCLOL_APP_ARGS"] = "--inherited-shim-argument" env["RCLOL_APP_ARG2"] = "--inherited-shim-argument-2" + env["MANGOHUD"] = "1" + env.pop("DISABLE_MANGOHUD", None) env["RCLOL_NATIVE_VPX"] = "1" env["RCLOL_LEAGUE_UX_TUNING"] = "1" # Inherited legacy settings must not re-enable inspection or unlimited frames. @@ -69,6 +71,9 @@ with open({str(log)!r}, "a") as output: ], "unexpected automatic helper" launches = [r for r in records if r["command"] == "darling"] assert len(launches) == 1, "unexpected launch count" + for record in records: + assert record["flags"]["MANGOHUD"] is None, "inherited MangoHud activation survived" + assert record["flags"]["DISABLE_MANGOHUD"] == "1", "MangoHud not disabled before a runtime helper" launch = launches[0] assert all(launch["flags"][key] is None for key in ( "RCLOL_APP_ARG3", "RCLOL_APP_ARG3_SLOT", "RCLOL_UX_ARG2", "RCLOL_UX_ARG2_SLOT" @@ -84,18 +89,23 @@ with open({str(log)!r}, "a") as output: assert "--log-dir=/Users/offline-check/Library/Logs/Riot Games/Riot Client" in launch["args"], "absolute log directory lost" # An inherited injection must also be absent for first-time installation. env["RIOT_LAUNCHER_HOST"] = str(folder / "Install Riot.app/Contents/MacOS/RiotClientServices") + env["DISABLE_MANGOHUD"] = "0" # An inherited value cannot override launcher policy. subprocess.run(["sh", str(launcher)], env=env, check=True, capture_output=True, text=True) install = json.loads(log.read_text().splitlines()[-1]) assert install["args"][0] == env["RIOT_LAUNCHER_HOST"] assert "--skip-to-install" in install["args"] assert not any(arg.startswith("--app-root=") for arg in install["args"]) assert install["flags"]["DYLD_INSERT_LIBRARIES"] is None + assert install["flags"]["MANGOHUD"] is None + assert install["flags"]["DISABLE_MANGOHUD"] == "1" env.pop("RIOT_LAUNCHER_HOST") env.pop("DYLD_INSERT_LIBRARIES") subprocess.run(["sh", str(launcher)], env=env, check=True, capture_output=True, text=True) clean = json.loads(log.read_text().splitlines()[-1]) assert clean["flags"]["DYLD_INSERT_LIBRARIES"] is None - print("LAUNCHER_OFFLINE pass=1 installed=PASS installer=PASS inherited_injection=absent runtime=preserved") + assert clean["flags"]["MANGOHUD"] is None + assert clean["flags"]["DISABLE_MANGOHUD"] == "1" + print("LAUNCHER_OFFLINE pass=1 installed=PASS installer=PASS inherited_injection=absent mangohud=disabled runtime=preserved") if __name__ == "__main__": diff --git a/tools/run-riot-client.sh b/tools/run-riot-client.sh index 75b6ec7..f33a612 100755 --- a/tools/run-riot-client.sh +++ b/tools/run-riot-client.sh @@ -2,6 +2,11 @@ # Launch Riot Client using the Darling runtime, without library injection. # Darling supplies Xlib Display pointers to EGL, so select X11 explicitly. set -eu +# Native MangoHud uses the guest PID against the host /proc view and can abort +# in GPU_fdinfo::find_fd (issue #38). Disable inherited implicit activation +# before any helper can start Darling, including first-time installation. +unset MANGOHUD +export DISABLE_MANGOHUD=1 # Native guest crashes created large system core files and exhausted this disk. # Address-only diagnostics suffice; bound this runner and its new namespace. if [ "${RCLOL_CORE_DUMPS:-0}" != 1 ]; then From f9d7f1a8ab8c91e72bb250b318e086eb3de95e2c Mon Sep 17 00:00:00 2001 From: lowell Date: Thu, 22 Oct 2026 08:01:47 +0300 Subject: [PATCH 2/6] Clamp the profile VRAM and report its GPU in system_profiler --- docs/PLATFORM_IDENTITY.md | 7 +++++++ tools/darling-system_profiler.sh | 24 ++++++++++++++++++------ tools/run-riot-client.sh | 3 +++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/PLATFORM_IDENTITY.md b/docs/PLATFORM_IDENTITY.md index f8be827..54f11a7 100644 --- a/docs/PLATFORM_IDENTITY.md +++ b/docs/PLATFORM_IDENTITY.md @@ -156,3 +156,10 @@ keeps no identity of its own, so it reports the same values as IOKit, including override saved by this tool. A field the guest does not provide is left out. `python3 -m unittest tests.test_system_profiler` checks the output with stub commands. + +`SPDisplaysDataType` reads the host DRM cards. With `DARLING_METAL_MAC_GPU_NAME` +set (the launcher default), an AMD or NVIDIA host card is reported as the +`MacBookPro16,1` discrete GPU: `AMD Radeon Pro 5500M`, vendor `0x1002`, device +`0x7340`, bus PCIe and VRAM from `DARLING_METAL_VRAM_MB` (4096 by default). This +keeps the display report consistent with `MTLDevice.name`; without the variable +the host card is reported as-is. diff --git a/tools/darling-system_profiler.sh b/tools/darling-system_profiler.sh index 540b101..f2c1f02 100644 --- a/tools/darling-system_profiler.sh +++ b/tools/darling-system_profiler.sh @@ -35,7 +35,11 @@ pci_name() { # vendor device (hex without 0x) -> "Vendor Model" done } -displays() { # one line per GPU: vendor|device|vram MB or empty|name +displays() { # one line per GPU: vendor|device|vram MB or empty|name|bus + # Same switch as the Metal device name: a Mac profile presents the MacBookPro16,1 + # discrete GPU instead of the host card, so system_profiler and Metal agree. + mac_spoof=0 + case "${DARLING_METAL_MAC_GPU_NAME:-}" in '') ;; 0) ;; *) mac_spoof=1;; esac for card in "$host"/sys/class/drm/card[0-9] "$host"/sys/class/drm/card[0-9][0-9]; do [ -r "$card/device/vendor" ] || continue vendor=$(sed 's/^0x//' "$card/device/vendor"); device=$(sed 's/^0x//' "$card/device/device") @@ -44,7 +48,14 @@ displays() { # one line per GPU: vendor|device|vram MB or empty|name vram=$(awk '{ printf "%d", $1 / 1048576 }' "$card/device/mem_info_vram_total") fi name=$(pci_name "$vendor" "$device"); [ -n "$name" ] || name="Display" - echo "$vendor|$device|$vram|$name" + bus=builtin + if [ "$mac_spoof" = 1 ]; then + case "$vendor" in + 1002|10de) vendor=1002; device=7340; name='AMD Radeon Pro 5500M' + vram=${DARLING_METAL_VRAM_MB:-4096}; bus=pcie;; + esac + fi + echo "$vendor|$device|$vram|$name|$bus" done } @@ -144,11 +155,11 @@ if [ "$xml" = 1 ]; then SPHardwareDataType) hardware | overview_xml hardware_overview;; SPSoftwareDataType) software | overview_xml os_overview;; SPDisplaysDataType) - displays | while IFS='|' read -r vendor device vram name; do + displays | while IFS='|' read -r vendor device vram name bus; do name=$(printf '%s' "$name" | escape) echo ' ' echo " _name$name" - echo ' spdisplays_busspdisplays_builtin' + echo " spdisplays_busspdisplays_$bus" echo " spdisplays_device-id0x$device" echo " spdisplays_vendor${name%% *} (0x$vendor)" [ -z "$vram" ] || echo " spdisplays_vram$vram MB" @@ -190,8 +201,9 @@ for type in $types; do SPSoftwareDataType) software | overview_text Software 'System Software Overview';; SPDisplaysDataType) printf 'Graphics/Displays:\n\n' - displays | while IFS='|' read -r vendor device vram name; do - printf ' %s:\n\n Chipset Model: %s\n Type: GPU\n Bus: Built-In\n' "$name" "$name" + displays | while IFS='|' read -r vendor device vram name bus; do + [ "$bus" = pcie ] && bus_text=PCIe || bus_text='Built-In' + printf ' %s:\n\n Chipset Model: %s\n Type: GPU\n Bus: %s\n' "$name" "$name" "$bus_text" [ -z "$vram" ] || printf ' VRAM (Total): %s MB\n' "$vram" printf ' Vendor: %s (0x%s)\n Device ID: 0x%s\n\n' "${name%% *}" "$vendor" "$device" done;; diff --git a/tools/run-riot-client.sh b/tools/run-riot-client.sh index 767294b..45a23e4 100755 --- a/tools/run-riot-client.sh +++ b/tools/run-riot-client.sh @@ -38,6 +38,9 @@ unset RCLOL_UX_ARG2 RCLOL_UX_ARG2_SLOT # Explicit 0 or an empty value selects the CPU fallback for diagnostics. # DARLING_METAL_MAC_GPU_NAME reports the MacBookPro16,1 GPU of the host vendor (AMD or Intel) as # MTLDevice.name, matching the model IOKit reports; memory figures stay the host's. +# VRAM clamp: honor an explicit DARLING_METAL_VRAM_MB, otherwise pin 4096 MB so the +# 5500M identity does not leak the host card's heap size. +export DARLING_METAL_VRAM_MB="${DARLING_METAL_VRAM_MB:-4096}" for option in RCLOL_GPU_DIRECT_PRESENT RCLOL_GPU_DIRECT_ASYNC RCLOL_GPU_DIRECT_VSYNC DARLING_CA_PRESENT_AT_COMMIT DARLING_CA_SKIP_LOCAL_IOSURFACE_RENDER RCLOL_FORWARD_MOUSE_MOVED RCLOL_MOUSE_CONFINEMENT DARLING_METAL_MAC_GPU_NAME; do eval 'value=${'"$option"'-1}' case "$value" in 0|'') unset "$option";; *) export "$option=$value";; esac From dd794377a9b07f50e6d6c352a2524687bb1d7b41 Mon Sep 17 00:00:00 2001 From: lowell Date: Thu, 22 Oct 2026 08:09:49 +0300 Subject: [PATCH 3/6] Write the Metal device log only on request --- docs/SETUP.md | 2 +- docs/TROUBLESHOOTING.md | 2 +- patches/cocotron.patch | 10 +++++++--- patches/metal--deps--indium.patch | 7 +++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/SETUP.md b/docs/SETUP.md index 0c0d39b..56e370c 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -164,7 +164,7 @@ The hand-off experiments (`metal-present-dispatch-wait`, `metal-deferred-blit` a | `/tmp/metal-skip-cpu-devices` | software Vulkan devices (lavapipe) are skipped while a hardware device exists | | `/tmp/metal-gpu` | diagnostic: selects the Vulkan device used for Metal by index or case-insensitive name substring instead of the loader's first device. The OpenGL context that presents does not follow it; see [hybrid laptops](TROUBLESHOOTING.md#hybrid-graphics-laptops-amdintel-igpu--nvidia). `METAL_INDIUM_GPU` is the environment equivalent; the file wins | | `/tmp/metal-all-devices` | a `VkDevice` is created for every supported Vulkan device, as before 2026-10-16. Without it only the selected device gets one; on a machine with lavapipe installed this also drops lavapipe's idle rasterizer threads | -| `/tmp/metal-no-drawable-vram` | drawables of a layer with `framebufferOnly` off (League sets it off) go back to host-visible system RAM, as before 2026-10-16. Without the file they are allocated in GPU memory like `framebufferOnly` drawables; nothing maps drawable memory from the CPU. On the RX 6600 this gave about 20 FPS more in a practice-tool fight and the same FPS when idle, not yet measured in an ARAM. `/tmp/metal-device.log` shows `drawable-vram=on` and `storage=vram` | +| `/tmp/metal-no-drawable-vram` | drawables of a layer with `framebufferOnly` off (League sets it off) go back to host-visible system RAM, as before 2026-10-16. Without the file they are allocated in GPU memory like `framebufferOnly` drawables; nothing maps drawable memory from the CPU. On the RX 6600 this gave about 20 FPS more in a practice-tool fight and the same FPS when idle, not yet measured in an ARAM. `/tmp/metal-device.log` (with `DARLING_METAL_DEVICE_LOG=1`) shows `drawable-vram=on` and `storage=vram` | | `/tmp/metal-no-lazy-wakeup` | every completion registration signals the event loop's wake-up semaphore from the CPU again, as before 2026-10-18. The handshake is per device. Without the file a registration signals only while the poller has announced a blocking wait (a spinning poller re-reads the registrations on its next pass, and its spin ends when one arrives). On the NVIDIA proprietary driver each `vkSignalSemaphore` is an RM control ioctl that waits on a driver-wide lock, about 0.3 ms each and ~25 per League frame, and it was the largest kernel cost of the submit worker. Re-read every 256 registrations; the wait log counts `wakeupSignalled` and `wakeupSkipped` | | `/tmp/metal-submit-batch-us` | the submit batch window in microseconds (500–100000, default 500); re-read every 256 checks, so it can be changed during a match. A presenting commit and every CPU wait still flush the batch at once. On the NVIDIA proprietary driver every `vkQueueSubmit2` is an RM control ioctl that waits on a driver-wide lock (about 0.4 ms each in a League match); with the default window a frame took about 8.5 submits, with `5000` about 2.5 (RTX 4090: 89 → 113 FPS, same match) | | `/tmp/metal-submit-batch-max` | command buffers per batch (1–256, default 16), re-read like the window; `64` lets one batch hold a whole frame | diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 13a2f7b..20703e6 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -434,7 +434,7 @@ The guest file `/tmp/metal-gpu` (a device index or part of its name, for example ### Check which GPU rendered -Each process that uses Metal appends to guest `/tmp/metal-device.log` (host `~/.darling/private/tmp/metal-device.log`): every Vulkan device the loader reported, the selected one and why, and the renderer of the presenting OpenGL context with both device UUIDs: +With `DARLING_METAL_DEVICE_LOG=1` in the launcher environment, each process that uses Metal appends to guest `/tmp/metal-device.log` (host `~/.darling/private/tmp/metal-device.log`): every Vulkan device the loader reported, the selected one and why, and the renderer of the presenting OpenGL context with both device UUIDs. The log is off by default because the guest can read it and it names the host GPU: ``` [MetalDevice] pid=… physical name="NVIDIA GeForce RTX 3060 Laptop GPU" type=discrete vendorID=0x10de … supported=yes diff --git a/patches/cocotron.patch b/patches/cocotron.patch index ce31983..2c04817 100644 --- a/patches/cocotron.patch +++ b/patches/cocotron.patch @@ -10019,12 +10019,13 @@ diff --git a/QuartzCore/CAMetalDrawable.mm b/QuartzCore/CAMetalDrawable.mm index d6f86b31..687f05d5 100644 --- a/QuartzCore/CAMetalDrawable.mm +++ b/QuartzCore/CAMetalDrawable.mm -@@ -31,6 +31,13 @@ +@@ -31,6 +31,14 @@ #include #include +#include +#include ++#include +#include +#include +#include @@ -10033,7 +10034,7 @@ index d6f86b31..687f05d5 100644 namespace DynamicVK = Indium::DynamicVK; static void reportGLErrors(void) { -@@ -50,8 +57,111 @@ static void reportGLErrors(void) { +@@ -50,8 +57,114 @@ namespace Indium::DynamicVK { static DynamicFunction vkGetSemaphoreFdKHR("vkGetSemaphoreFdKHR"); static DynamicFunction vkGetMemoryFdKHR("vkGetMemoryFdKHR"); @@ -10057,8 +10058,11 @@ index d6f86b31..687f05d5 100644 + } +} + -+// Same line format as Indium's device log. ++// Same line format as Indium's device log; off unless DARLING_METAL_DEVICE_LOG is ++// set, so the guest-readable file does not name the host GPU by default. +static void appendDeviceLog(const std::string& line) { ++ const char* enabled = getenv("DARLING_METAL_DEVICE_LOG"); ++ if (!enabled || !*enabled || (enabled[0] == '0' && !enabled[1])) return; + if (FILE* log = fopen("/tmp/metal-device.log", "a")) { + fprintf(log, "[MetalDevice] pid=%d %s\n", getpid(), line.c_str()); + fclose(log); diff --git a/patches/metal--deps--indium.patch b/patches/metal--deps--indium.patch index f3c149f..c6d11ab 100644 --- a/patches/metal--deps--indium.patch +++ b/patches/metal--deps--indium.patch @@ -2884,7 +2884,7 @@ index 322e186..f712c7a 100644 #include #include #include -@@ -12,39 +17,207 @@ +@@ -12,39 +17,210 @@ #include @@ -2911,8 +2911,11 @@ index 322e186..f712c7a 100644 + // device list is built, plus one when the presenting OpenGL context first + // imports a Vulkan drawable. It exists so a user can tell us which GPU + // actually rendered a match, which the game's own logs and FPS numbers do not -+ // show. ++ // show. Off by default: the guest can read this file, so enabling it names the ++ // host GPU to anything running in the prefix. Set DARLING_METAL_DEVICE_LOG=1. + void appendDeviceLog(const std::string& line) { ++ const char* enabled = getenv("DARLING_METAL_DEVICE_LOG"); ++ if (!enabled || !*enabled || (enabled[0] == '0' && !enabled[1])) return; + if (FILE* log = fopen("/tmp/metal-device.log", "a")) { + fprintf(log, "[MetalDevice] pid=%d %s\n", getpid(), line.c_str()); + fclose(log); From 2d0b6cf35191d88e55b44f97ae3bf4abd581b438 Mon Sep 17 00:00:00 2001 From: lowell Date: Thu, 22 Oct 2026 13:06:30 +0300 Subject: [PATCH 4/6] Drop host session names from the optional guest environment filter --- tools/exec-guest.py | 14 ++++++++++++++ tools/run-riot-client.sh | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/tools/exec-guest.py b/tools/exec-guest.py index 331f754..71a55dd 100755 --- a/tools/exec-guest.py +++ b/tools/exec-guest.py @@ -16,6 +16,12 @@ SESSION_PREFIXES = ( 'XDG_SESSION_', 'XDG_SEAT', 'XDG_VTNR', 'XDG_CURRENT_DESKTOP', 'XDG_MENU_PREFIX', 'GNOME_', 'KDE_', 'GDM', 'SSH_', 'SYSTEMD_', 'MEMORY_PRESSURE_', 'QT_', 'GTK_', 'GDK_', 'GIO_', 'GSETTINGS_', 'GJS_', 'FLATPAK_', 'SNAP_', 'KONSOLE_', 'TERM_PROGRAM', 'BASH_FUNC_', + # Host shell, prompt and developer-tool metadata. None of it exists on a Mac and + # several entries name Linux paths, so the guest must not inherit them. + 'STARSHIP_', 'ILLOGICAL_IMPULSE_', 'INIR_', 'PNPM_', 'YARN_', 'npm_config_', 'PIP_', + 'CARGO_', 'GIT_', 'LESS_TERMCAP_', '_P9K_', 'VSSCRIPT_', 'ORCA_', 'CLAUDE', 'TF_', + 'CUDA_', 'COMPOSER_', 'DEBIAN_', 'FZF_', 'BAT_', 'MYSQL_', 'AWS_', 'LESS', + 'CLOUDSDK_', 'GH_', 'GLAB_', 'HOMEBREW_', 'ELECTRON_', 'DELTA_', 'HIST', 'GPG_', ) SESSION_NAMES = { 'WAYLAND_DISPLAY', 'DESKTOP_SESSION', 'DESKTOP_STARTUP_ID', 'SESSION_MANAGER', @@ -23,6 +29,9 @@ SESSION_NAMES = { 'LISTEN_FDS', 'LISTEN_PID', 'LISTEN_FDNAMES', 'COLORTERM', 'VTE_VERSION', 'WINDOWID', 'WINDOWPATH', 'CHROME_DESKTOP', 'NO_AT_BRIDGE', 'MOTD_SHOWN', 'SNAP', 'APPIMAGE', 'APPDIR', 'OWD', 'VIRTUAL_ENV', 'DEBUGINFOD_URLS', 'LS_COLORS', 'COLORFGBG', 'OLDPWD', 'SHLVL', + 'AGENT', 'NO_COLOR', 'TERM', 'VISUAL', 'PROMPT_COMMAND', 'HISTFILE', 'HISTSIZE', + 'SAVEHIST', 'HISTORY_IGNORE', 'PYTHONUNBUFFERED', 'LINES', 'COLUMNS', '_', + 'CI', 'EDITOR', 'PAGER', 'GIT_PAGER', 'SYSTEMD_PAGER', 'MANPAGER', } GUEST_SHELL = '/bin/zsh' @@ -40,6 +49,11 @@ def filter_host_environment(environ): # The host login shell (for example /bin/fish) does not exist in the guest. if 'SHELL' not in keep: environ['SHELL'] = GUEST_SHELL + # A host PATH names Linux directories; the guest always has the Mac layout. + if 'PATH' not in keep: + environ['PATH'] = '/usr/bin:/bin:/usr/sbin:/sbin' + environ.pop('RCLOL_KEEP_HOST_ENV', None) + environ.pop('RCLOL_FILTER_HOST_ENV', None) return removed diff --git a/tools/run-riot-client.sh b/tools/run-riot-client.sh index 45a23e4..332d675 100755 --- a/tools/run-riot-client.sh +++ b/tools/run-riot-client.sh @@ -46,6 +46,11 @@ for option in RCLOL_GPU_DIRECT_PRESENT RCLOL_GPU_DIRECT_ASYNC RCLOL_GPU_DIRECT_V case "$value" in 0|'') unset "$option";; *) export "$option=$value";; esac done prefix=$prefix_dir +# Resolve the loader before the environment filter replaces PATH with the Mac layout. +darling_bin=$(command -v darling) || { + echo 'darling loader not found in PATH' >&2 + exit 1 +} # RIOT_GUEST_HOME is host-side; DYLD paths must be relative to the guest root. case "$guest_home" in "$prefix"/*) guest_path=/${guest_home#"$prefix"/} ;; @@ -136,6 +141,6 @@ exec python3 "$runner_dir/exec-guest.py" env -u ELECTRON_RUN_AS_NODE -u DYLD_INS DYLD_LIBRARY_PATH="${DYLD_LIBRARY_PATH:-$guest_path/RuntimeLibraries}" \ DYLD_FRAMEWORK_PATH="${DYLD_FRAMEWORK_PATH:-$guest_path/RuntimeFrameworks}" \ DARLING_XSHM_LIBRARY="${DARLING_XSHM_LIBRARY:-$guest_path/libDarlingXShm.dylib}" \ - darling "$A" --region="${RCLOL_REGION:-EUW}" --locale="${RCLOL_LOCALE:-en_GB}" \ + "$darling_bin" "$A" --region="${RCLOL_REGION:-EUW}" --locale="${RCLOL_LOCALE:-en_GB}" \ "$@" \ --log-dir="$guest_path/Library/Logs/Riot Games/Riot Client" From 7ff91e81a474f30bdf43589d52a0eb1123ec8ad3 Mon Sep 17 00:00:00 2001 From: lowell Date: Thu, 22 Oct 2026 17:48:01 +0300 Subject: [PATCH 5/6] Align the Intel display identity and validate the VRAM override --- docs/PLATFORM_IDENTITY.md | 8 +++++--- tools/darling-system_profiler.sh | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/PLATFORM_IDENTITY.md b/docs/PLATFORM_IDENTITY.md index 54f11a7..9714821 100644 --- a/docs/PLATFORM_IDENTITY.md +++ b/docs/PLATFORM_IDENTITY.md @@ -160,6 +160,8 @@ commands. `SPDisplaysDataType` reads the host DRM cards. With `DARLING_METAL_MAC_GPU_NAME` set (the launcher default), an AMD or NVIDIA host card is reported as the `MacBookPro16,1` discrete GPU: `AMD Radeon Pro 5500M`, vendor `0x1002`, device -`0x7340`, bus PCIe and VRAM from `DARLING_METAL_VRAM_MB` (4096 by default). This -keeps the display report consistent with `MTLDevice.name`; without the variable -the host card is reported as-is. +`0x7340`, bus PCIe and VRAM from `DARLING_METAL_VRAM_MB` (4096 by default; a +value that is not a positive decimal keeps the default). An Intel card is +reported as `Intel UHD Graphics 630` on bus Built-In with shared memory, as +`MTLDevice.name` does. This keeps the display report consistent with Metal; +without the variable the host card is reported as-is. diff --git a/tools/darling-system_profiler.sh b/tools/darling-system_profiler.sh index f2c1f02..401f68e 100644 --- a/tools/darling-system_profiler.sh +++ b/tools/darling-system_profiler.sh @@ -52,7 +52,12 @@ displays() { # one line per GPU: vendor|device|vram MB or empty|name|bus if [ "$mac_spoof" = 1 ]; then case "$vendor" in 1002|10de) vendor=1002; device=7340; name='AMD Radeon Pro 5500M' - vram=${DARLING_METAL_VRAM_MB:-4096}; bus=pcie;; + vram=${DARLING_METAL_VRAM_MB:-4096} + case "$vram" in ''|*[!0-9]*) vram=4096;; esac + [ "$vram" -eq 0 ] 2>/dev/null && vram=4096 + bus=pcie;; + 8086) vendor=8086; device=3e9b; name='Intel UHD Graphics 630' + vram=; bus=builtin;; esac fi echo "$vendor|$device|$vram|$name|$bus" From 913e81887e42e6500a1a6e799b23cef6ddd10e33 Mon Sep 17 00:00:00 2001 From: lowell Date: Thu, 22 Oct 2026 19:21:00 +0300 Subject: [PATCH 6/6] Fall back before an oversized VRAM override reaches the shell test --- tools/darling-system_profiler.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/darling-system_profiler.sh b/tools/darling-system_profiler.sh index 401f68e..7719431 100644 --- a/tools/darling-system_profiler.sh +++ b/tools/darling-system_profiler.sh @@ -54,7 +54,11 @@ displays() { # one line per GPU: vendor|device|vram MB or empty|name|bus 1002|10de) vendor=1002; device=7340; name='AMD Radeon Pro 5500M' vram=${DARLING_METAL_VRAM_MB:-4096} case "$vram" in ''|*[!0-9]*) vram=4096;; esac - [ "$vram" -eq 0 ] 2>/dev/null && vram=4096 + # Keep the numeric test overflow-safe: a long digit string must + # fall back before the shell compares it. + if [ "${#vram}" -gt 7 ] || [ "$vram" -eq 0 ] || [ "$vram" -gt 1048576 ]; then + vram=4096 + fi bus=pcie;; 8086) vendor=8086; device=3e9b; name='Intel UHD Graphics 630' vram=; bus=builtin;;