mirror of
https://github.com/games-on-whales/wolf.git
synced 2026-10-15 13:02:03 +00:00
[PR #438] [MERGED] fix(docker): resume the running session instead of killing its container on re-launch #467
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#467
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?
📋 Pull Request Information
Original PR: https://github.com/games-on-whales/wolf/pull/438
Author: @wolph
Created: 6/21/2026
Status: ✅ Merged
Merged: 6/23/2026
Merged by: @ABeltramo
Base:
stable← Head:fix/stale-container-monitor-loop📝 Commits (1)
a28adc3fix: resume an existing session instead of killing its container on re-launch📊 Changes
3 files changed (+22 additions, -1 deletions)
View changed files
📝
src/moonlight-server/rest/endpoints.hpp(+15 -0)📝
src/moonlight-server/runners/docker.cpp(+2 -1)📝
tests/docker/testDocker.cpp(+5 -0)📄 Description
Summary
Re-launching or reconnecting to an app a client is already running dropped the player back to a fresh launcher: the running container was destroyed and recreated, and the old runner's monitor thread was left polling the now-gone container, logging
[CURL] error 404 - No such container.(This started as an attempt at #364, but per discussion that issue looks unrelated — this is a distinct re-launch/reconnect bug that reproduces on its own.)
Root cause
session_idis derived from the client certificate (state/sessions.hpp), so the app container name"{app}_{session_id}"is stable across reconnects.launch()(rest/endpoints.hpp) does no dedup — it always starts a runner →RunDocker::run→DockerAPI::create(). Withforce_recreate_if_presentdefaulting totrue, a name conflict makescreate()remove the still-running container out from under the first runner. That first runner's monitor loop then dereferenced the now-emptyget_by_id()optional (UB).resume()is the correct re-init path: it reuses the session and carries over the wayland display + devices without starting a runner.launch()just never checked.Changes
rest/endpoints.hpp—launch()delegates toresume()when the client already has a running session, so the container is reused (and the wayland display + devices carried over) instead of recreated. This is the actual fix.runners/docker.cpp— guard the monitor loop'sget_by_id(...)->statuswithvalue_or(Container{.status = EXITED})so a container that has gone away is treated as not-running and the loop exits cleanly, rather than dereferencingstd::nullopt. (This is the original change from the first round of review.)tests/docker/testDocker.cppadds a small regression assertingget_by_id()returnsstd::nulloptfor a removed / non-existent container.Reproduced + verified end-to-end
Reproduced the bug and verified the fix on a real Wolf instance (RTX 4090); a self-contained reproducer script and before/after output are in a comment below. Two
/launchcalls for the same app+client:already present, removing first+ aNo such container404 loop;launch()routes toresume(). GPU pipeline still comes up normally.Notes
Changed files are
clang-format(v18) clean. Layer 1 (launch()→resume()) is protocol-facing — happy to adjust the routing/policy if you'd prefer a different approach at the session layer.(An earlier revision also added a
DockerAPI::get_by_name+ a reattach-to-running-container path in the runner as defense-in-depth; dropped it to keep this focused, sincelaunch()→resume()already prevents the duplicate runner.)🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.