mirror of
https://github.com/games-on-whales/wolf.git
synced 2026-10-15 21:12:08 +00:00
[GH-ISSUE #501] Zero-copy NVIDIA pipeline crashes (GsCUDABuf/apply_video_info) on 2nd+ app launch — WOLF_USE_ZERO_COPY=FALSE works around it #305
Labels
No labels
🧠 1 - 🤖 999
AMD
bug
bug
cannot reproduce
documentation
duplicate
easy
enhancement
enhancement
enhancement
fixed?
fixed?
good first issue
hard
help wanted
Intel
invalid
LXC
medium
moonlight-protocol
Multi GPU
nixos
not a bug
nvidia
pull-request
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
games-on-whales/wolf#305
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jdonaldson on GitHub (Sep 14, 2026).
Original GitHub issue: https://github.com/games-on-whales/wolf/issues/501
Summary
Under the zero-copy NVIDIA pipeline (default,
WOLF_USE_ZERO_COPYunset), the first app launched in a Wolf process streams fine, but every subsequent app launch in the same process crashes with a panic inGsCUDABuf/apply_video_info, and the crash is severe enough that it sometimes segfaults the wholewolfprocess (exit status 11), auto-restarted by supervisord.Workaround confirmed: setting
WOLF_USE_ZERO_COPY=FALSEavoids the crash entirely — verified stable with two app containers (Wolf-UIand a customSteamapp) running concurrently, where the zero-copy path had crashed on the second launch every time it was tried.Filing this because
AGENTS.mddocuments that zero-copy is supposed to "auto-fall back to legacy when an encoder can't support it" — that fallback doesn't appear to be triggering here even though the zero-copy path is reliably broken in this environment, so I think the auto-fallback logic (rather than just the crash itself) is the actual bug.Environment
linux-image-amd64kernel (6.12.107+deb13-amd64) — not the Debian cloud kernel flavor, which lacksuinputand workingnvidia_drmmodeset entirely (separate issue, not filing that one, just noting for reproduction)ghcr.io/games-on-whales/wolf:stablegow/nvidia-drivervolume +NVIDIA_DRIVER_VOLUME_NAME), notnvidia-container-toolkit/runtime: nvidia— switched to this specifically because the container-toolkit method hit the sameGsCUDABufcrash on the very first launch (matches #379), and the manual method fixed that specific casenetwork_mode: host, container runprivileged: trueSecondary finding, possibly related
wolf:stable's image bundles a stale/usr/local/nvidia/lib/libnvrtc.so.11.0dated Aug 2020 — neither the container-toolkit method nor the manual driver-volume method touches this path (NVRTC is a CUDA Toolkit component, not shipped by either the driver.runinstaller or the container toolkit's device injection). Every boot logs:(
nvrtcGetCUBINSizewas added in CUDA 11.2 — the bundled file is CUDA 11.0.)nvcodecstill gets selected as the encoder despite this warning, so it's not obviously fatal on its own, but I wonder if it's what's actually causing the zero-copy path's CUDA context/buffer allocation to be unreliable, which would explain why the auto-fallback should be kicking in but isn't. I tried bind-mounting a real CUDA 12libnvrtc.soover the stale file as a workaround — that made things worse (brokecudaconvertscaleentirely, forcing full software encoding), presumably an ABI mismatch with sibling libraries in that same bundled set, so that's not a viable fix on its own.Repro steps
WOLF_USE_ZERO_COPYunset (default/on).Note: the first app's underlying container/session does not appear to fully tear down when the Moonlight client just navigates back to the app grid —
Stopped container: /Wolf-UI_...in the log lands ~20-30s after the second app's launch already failed, suggesting overlapping GPU/CUDA context lifetimes between the two sessions. Fully disconnecting the Moonlight client (not just backing out to the app grid) before the second launch did not avoid the crash either.Crash (zero-copy path, default)
and, in another occurrence of the same underlying crash:
Both times, immediately followed by:
On at least one occurrence, this escalated to a full
wolfprocess crash, auto-restarted by supervisord:...and a separate shutdown-time stack trace directly implicated
/usr/nvidia/lib/libcuda.so.1(not just Wolf's own code) in a SIGTERM-triggered crash, though I don't have the full trace saved for that one.I also saw, on a different attempt, a non-panicking but still fatal caps-negotiation failure at this same point, reproduced identically at three different resolutions (1280×720, 1920×1080, and 3456×2160 — ruling out resolution as a variable):
Confirmed working with
WOLF_USE_ZERO_COPY=FALSESame environment, same two-app sequence,
WOLF_USE_ZERO_COPY=FALSEset:Both
Wolf-UIand the Steam app containers ran concurrently (docker psshowing bothUp) with no crash. There was a similar-looking transient warning during the second app's launch (transform could not transform video/x-raw, format=(string)RGBx... warning: not negotiated), but unlike the zero-copy path, the pipeline recovered and the container stayed up rather than exiting.Ask
libnvrtc.so.11.0is the actual root cause (rather than something inherent to zero-copy + concurrent sessions), a fix there might be higher-leverage than fixing the fallback logic alone.Happy to gather more diagnostics (full logs,
WOLF_LOG_LEVEL=DEBUGoutput, etc.) — this environment is still up and I can reproduce reliably.Diagnosed with help from Claude Code (Anthropic) — I've verified the log excerpts and repro steps above against my own session, but flagging the AI assistance for transparency.
@r0b0tb4c0n commented on GitHub (Sep 18, 2026):
i think i ran into this same issue yesterday/today and didn't see your issue. i made a pr but if you'd be willing to test to see if it fixes your issue as well, i'd love to have another set of eyes on it. the issue i opened is #504 let me know if you need help building the image. I'm using nvidia-open 615.71.09-1 but our errors seem to be the same
@jdonaldson commented on GitHub (Sep 21, 2026):
Thanks for the offer, @r0b0tb4c0n — much appreciated, and sorry for the slow reply.
I built both images to A/B your #505 (stable @
2273b2e, and the same commit plus your patch, so they differ only by the fix). Before running it I went back through the resume path, and I now think the root cause sits a layer above the CUDA context.The trigger in both our reports looks like re-entering a session that is still running — not app-switching, which is how I originally described it in this issue. That also explains the asymmetry you spotted: closing with the ✕ leaves the session up, so the next connect is a resume, while
ctrl-alt-shift-qends it, so the next connect is a clean launch.Two separate things in
resume()(rest/endpoints.hpp):It double-responds on success — the trailing
server_error()is at function scope, so a successful resume emits200+ resume XML followed by400+ error XML. Filed as #509, fix in #510. Cosmetic next to the crash, but it means a successful resume and a failed one look identical on the wire, which makes this path miserable to debug.It never stops the old pipeline. It swaps the session record and moves the
wayland_displayand input devices onto a new session id, but fires neitherPauseStreamEventnorStopStreamEvent— those only come from the control channel and the API. Meanwhile thePauseStreamEventhandler instreaming/streaming.cppstates the requirement outright: "The only solution is to kill the pipeline and re-create it again when a resume happens." So the old pipeline is left running on the same Wayland display, and its session id is already out ofrunning_sessions, so nothing can stop it by id afterwards.Observed on my box: a Wolf-UI stream ended at
01:16:14andStopped container: /Wolf-UI_...did not appear until11:39:20— the session lingered about ten hours. Any reconnect inside that window is a re-entry into a live session.If that reading is right, #505 helps on one side of a race — cached context already destroyed, cache still pointing at it — but when the old pipeline is still alive and owns the context, the validity probe passes, the context is reused for a second concurrent pipeline, and you get the original collision. Worth noting too that your driver is nvidia-open 615.71.09 and mine is 550.163.01 proprietary, so we may not even be landing on the same side of that race.
So my plan is to try correcting the underlying lifetime issue first, then treat the symptom, and separately give the user better ground truth about what happened — as it stands, a re-entry neither resumes cleanly nor tells you the session is still up. I'll still report back with the #505 A/B either way; the two aren't mutually exclusive and your guard looks reasonable regardless of what sits underneath it.
Analysis assisted by Claude Code; code references and timestamps above were checked against the repository and my own logs before posting.