fix(iokitd): run without an X display instead of crashing in a loop

With DISPLAY set but XAUTHORITY missing or stale, the X server rejects the
connection, XOpenDisplay() returns NULL, and iokitd passed that NULL display
to eglGetPlatformDisplay(). Mesa's X11 platform expects a real Display there,
so iokitd faulted and launchd restarted it every 10 seconds while /tmp/lolsig.log
filled with frames (issue #140).

IOSurfaceRoot now checks the display first, stays at EGL_NO_DISPLAY and prints
one line when it is missing. createSurface() already returns KERN_FAILURE for
!hasDisplay(), so surfaces fail closed instead of the process crashing. The
destructor also skips eglTerminate() when no display was initialized.

Documents that DISPLAY alone is not enough on servers and SSH sessions, and
adds a display probe to tools/env-check.sh: it reports DISPLAY/XAUTHORITY and
warns when xdpyinfo cannot open the display that Darling will inherit.

Signed-off-by: zero <zero@localhost>
This commit is contained in:
zero committed 2026-10-25 13:37:53 -06:00
1 parent 24276b91c6
commit 9a1a38b568
3 files changed
+61 -3

No files matched your search

+14
View File
@@ -434,6 +434,20 @@ The installer adds a CarbonCore framework override and the matching absolute Cor
`iokitd` crashed in host glibc's `pthread_mutex_lock` and launchd restarted it every 10 seconds. It called `eglGetDisplay()` with an Xlib display, so Mesa picked the platform from `EGL_PLATFORM`. Wayland sessions often set that to `wayland`, and the first `darling` command passes its environment to every guest service, including `iokitd`. `scripts/run.sh` sets `EGL_PLATFORM=x11` and was unaffected, but `darling shell` from a Wayland terminal (including the one in `scripts/install-runtime.sh`) started the loop. `iokitd` now requests the X11 platform explicitly. The fix is part of the base install (`sudo cmake --install`); until then, start Darling with `EGL_PLATFORM=x11`.
## `iokitd` restarts when the X display is not accessible
`DISPLAY` can name an X server that rejects the connection, which is what an unset or stale `XAUTHORITY` does on a server, over SSH, or in a `sudo` session that dropped the cookie. `iokitd` then has no Xlib display and previously still called into EGL with a null display, so the process faulted and launchd restarted it in a loop while `/tmp/lolsig.log` filled with frames ([#140](https://github.com/lucannez64/darling-lol/issues/140)).
`iokitd` now checks the display before EGL. Without a usable display it prints one line (`iokitd: cannot open X display …; X11 surface acceleration disabled`) and keeps running, so `darling shell` starts instead of crash-looping. Surfaces then fail with `KERN_FAILURE`, which means the guest has no GPU rendering: export a cookie the user running Darling can read and start again, for example:
```sh
export XAUTHORITY=/run/user/$(id -u)/xauth
# or, from a server install that keeps its cookie elsewhere:
XAUTHORITY=$(ls /var/run/sddm/* | head -1) DISPLAY=:0 EGL_PLATFORM=x11 darling shell echo hola
```
`bash tools/env-check.sh` now probes the display with `xdpyinfo` in the environment Darling inherits and warns when it cannot open it. That check is advisory: without X11/EGL the runtime still boots, but the game cannot render.
## Blocky video or flickering startup logo
The first dynamically resolved GL call could lose floating-point arguments during ELF symbol lookup. Chromium's linear sampler request then failed and left nearest sampling. The generated resolver now preserves those registers. Install both the rebuilt native `libGL.dylib` in `RuntimeLibraries` and the OpenGL framework's library copy using the paired runtime installer; the framework alone is insufficient.
+29 -3
View File
@@ -437,10 +437,10 @@ index 50c10fe..7026e1c 100644
+ return kIOReturnSuccess;
+}
diff --git a/src/IOSurfaceRoot.mm b/src/IOSurfaceRoot.mm
index d7e6fab..d860582 100644
index d7e6fab..f47889f 100644
--- a/src/IOSurfaceRoot.mm
+++ b/src/IOSurfaceRoot.mm
@@ -21,13 +21,17 @@
@@ -21,13 +21,33 @@
#include "iokitd.h"
#include "IOSurface.h"
#include "IODisplayConnectX11.h"
@@ -448,6 +448,7 @@ index d7e6fab..d860582 100644
#include <IOKit/IOCFUnserialize.h>
#include <stdexcept>
#include <iostream>
+#include <cstdlib>
IOSurfaceRoot::IOSurfaceRoot()
{
@@ -455,10 +456,35 @@ index d7e6fab..d860582 100644
+ // The native display is an Xlib Display. eglGetDisplay() would let Mesa
+ // guess the platform from EGL_PLATFORM, which Wayland sessions often set
+ // to "wayland"; Mesa then treats the Display as a wl_display and crashes.
+ m_display = eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, IODisplayConnectX11::getDisplay(), NULL);
+ Display* display = IODisplayConnectX11::getDisplay();
+ // Mesa's X11 platform dereferences the native display, so a NULL display
+ // faults. XOpenDisplay() returns NULL when the X server rejects the
+ // connection, which is what an unset or stale XAUTHORITY does. iokitd then
+ // crashed and launchd restarted it in a loop. Run without EGL instead;
+ // createSurface() already reports KERN_FAILURE when hasDisplay() is false.
+ if (!display)
+ {
+ m_display = EGL_NO_DISPLAY;
+ std::cerr << "iokitd: cannot open X display "
+ << (std::getenv("DISPLAY") ? std::getenv("DISPLAY") : "(DISPLAY unset)")
+ << "; X11 surface acceleration disabled, set XAUTHORITY to a readable cookie"
+ << std::endl;
+ return;
+ }
+ m_display = eglGetPlatformDisplay(EGL_PLATFORM_X11_KHR, display, NULL);
if (m_display == EGL_NO_DISPLAY)
return;
@@ -50,7 +70,8 @@ IOSurfaceRoot::IOSurfaceRoot()
IOSurfaceRoot::~IOSurfaceRoot()
{
- eglTerminate(m_display);
+ if (m_display != EGL_NO_DISPLAY)
+ eglTerminate(m_display);
}
IOSurfaceRoot* IOSurfaceRoot::instance()
diff --git a/src/PowerSources.mm b/src/PowerSources.mm
new file mode 100644
index 0000000..70ca9bd
+18
View File
@@ -20,4 +20,22 @@ command -v darling >/dev/null && darling --version 2>&1 || echo "darling not ins
echo "== gpu =="
ls /dev/dri 2>/dev/null || echo "no /dev/dri (Vulkan render needs GPU or lavapipe)"
command -v vulkaninfo >/dev/null && vulkaninfo --summary 2>&1 | head -20 || echo "vulkaninfo absent"
echo "== display =="
# DISPLAY is not enough: the X server can reject the connection when the cookie
# is missing or stale, and Darling's iokitd then has no X11/EGL path. Ask the
# server with the environment Darling will inherit.
if [ -n "${DISPLAY:-}" ]; then
echo "DISPLAY=$DISPLAY XAUTHORITY=${XAUTHORITY:-unset}"
if command -v xdpyinfo >/dev/null 2>&1; then
if xdpyinfo >/dev/null 2>&1; then
echo "X display reachable"
else
echo "WARN: cannot open $DISPLAY; export XAUTHORITY with a readable cookie (typical for servers and SSH), otherwise iokitd runs without X11/EGL"
fi
else
echo "xdpyinfo not installed; skipping the display probe (install x11-utils)"
fi
else
echo "DISPLAY unset; iokitd runs without X11/EGL (expected on a headless host)"
fi
[ "$ok" -eq 1 ] && echo "OK" || { echo "FAIL: install missing tools"; exit 1; }