[GH-ISSUE #17] Lobbies are always created with stop_when_everyone_leaves=false, so app containers are never reaped #11

Open
opened 2026-10-15 13:01:25 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @davidrusho on GitHub (Sep 9, 2026).
Original GitHub issue: https://github.com/games-on-whales/wolf-ui/issues/17

Every lobby Wolf-UI creates is hardcoded to stop_when_everyone_leaves = false, in both the solo and the co-op path:

  • src/Scenes/Main/Body/Apps/App.cs:360 (OnStartPressed → StopWhenEveryoneLeaves = false)
  • src/Scenes/Main/Body/Apps/App.cs:439 (OnCoopPressed → same)

Wolf only tears a lobby's runner down when leave_lobby() sees that flag true and the lobby empty (sessions/lobbies.cpp:61). With it false, no StopLobbyEvent is fired, the docker runner stays parked in its do..while on container status, and the cleanup block guarded by WOLF_STOP_CONTAINER_ON_EXIT (runners/docker.cpp:294) is never reached.

I understand the intent — the Stop button in the app menu exists precisely so a session can outlive a disconnect, and #6 is someone wanting exactly that while a game downloads. The problem is that nothing bounds it. Each launch mints a fresh lobby UUID, so the containers never collide and never self-clean the way the Wolf-UI container does (it keys on a fixed per-client folder id and logs Container already present, removing first). On my box, with an RTX 3090 shared between this and other workloads, that means every streaming session I forget to Stop leaves a container holding ~200 MiB of VRAM and pinning the card in P2 at ~110 W indefinitely — measured 24 W once the stale lobbies are stopped.

The gap that makes it easy to hit: disconnecting from Moonlight sends ENet TERMINATION/DISCONNECT, which fires PauseStreamEvent only (control/control.cpp:179,207) — so closing the client looks to the user exactly like ending the session, but reaps nothing. The docs also point the other way: WOLF_STOP_CONTAINER_ON_EXIT is documented as governing "force stop and removal of containers when the connection is closed", which is what I assumed applied here. The Lobbies page in the dev docs is currently a WIP… stub, so there is nowhere to find the real rule.

Two things that would help, either one on its own:

  1. Make it a per-app setting rather than a hardcoded literal — the Lobby model already carries the field, so this is exposing it in the app's config rather than new mechanism. "Keep running after I disconnect" is genuinely wanted for a downloading game and genuinely unwanted for a game I just finished.
  2. An optional idle timeout — stop a lobby that has had no connected sessions for N minutes. That covers the forgetful case without taking the deliberate one away.

For now I poll GET /api/v1/lobbies on a timer and POST /api/v1/lobbies/stop for any lobby whose connected_sessions has been empty for 30 minutes, which works well. Happy to open a PR for either option if you'd like one and can say which shape you'd prefer.

Versions: wolf stable @ 2273b2e6, wolf-ui main.

Originally created by @davidrusho on GitHub (Sep 9, 2026). Original GitHub issue: https://github.com/games-on-whales/wolf-ui/issues/17 Every lobby Wolf-UI creates is hardcoded to `stop_when_everyone_leaves = false`, in both the solo and the co-op path: - `src/Scenes/Main/Body/Apps/App.cs:360` (`OnStartPressed` → `StopWhenEveryoneLeaves = false`) - `src/Scenes/Main/Body/Apps/App.cs:439` (`OnCoopPressed` → same) Wolf only tears a lobby's runner down when `leave_lobby()` sees that flag true and the lobby empty ([`sessions/lobbies.cpp:61`](https://github.com/games-on-whales/wolf/blob/stable/src/moonlight-server/sessions/lobbies.cpp#L61)). With it false, no `StopLobbyEvent` is fired, the docker runner stays parked in its `do..while` on container status, and the cleanup block guarded by `WOLF_STOP_CONTAINER_ON_EXIT` ([`runners/docker.cpp:294`](https://github.com/games-on-whales/wolf/blob/stable/src/moonlight-server/runners/docker.cpp#L294)) is never reached. I understand the intent — the Stop button in the app menu exists precisely so a session can outlive a disconnect, and #6 is someone wanting exactly that while a game downloads. The problem is that nothing bounds it. Each launch mints a fresh lobby UUID, so the containers never collide and never self-clean the way the Wolf-UI container does (it keys on a fixed per-client folder id and logs `Container already present, removing first`). On my box, with an RTX 3090 shared between this and other workloads, that means every streaming session I forget to Stop leaves a container holding ~200 MiB of VRAM and pinning the card in P2 at ~110 W indefinitely — measured 24 W once the stale lobbies are stopped. The gap that makes it easy to hit: disconnecting from Moonlight sends ENet `TERMINATION`/`DISCONNECT`, which fires `PauseStreamEvent` only ([`control/control.cpp:179,207`](https://github.com/games-on-whales/wolf/blob/stable/src/moonlight-server/control/control.cpp#L179)) — so closing the client looks to the user exactly like ending the session, but reaps nothing. The docs also point the other way: `WOLF_STOP_CONTAINER_ON_EXIT` is documented as governing "force stop and removal of containers when the connection is closed", which is what I assumed applied here. The Lobbies page in the dev docs is currently a `WIP…` stub, so there is nowhere to find the real rule. Two things that would help, either one on its own: 1. **Make it a per-app setting** rather than a hardcoded literal — the `Lobby` model already carries the field, so this is exposing it in the app's config rather than new mechanism. "Keep running after I disconnect" is genuinely wanted for a downloading game and genuinely unwanted for a game I just finished. 2. **An optional idle timeout** — stop a lobby that has had no connected sessions for N minutes. That covers the forgetful case without taking the deliberate one away. For now I poll `GET /api/v1/lobbies` on a timer and `POST /api/v1/lobbies/stop` for any lobby whose `connected_sessions` has been empty for 30 minutes, which works well. Happy to open a PR for either option if you'd like one and can say which shape you'd prefer. Versions: wolf `stable` @ `2273b2e6`, wolf-ui `main`.
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
games-on-whales/wolf-ui#11
No description provided.