[GH-ISSUE #518] Leaving a lobby can leak every frame until Wolf is OOM-killed (gst-interpipe use-after-free) #314

Open
opened 2026-10-15 12:59:35 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @gorylpe on GitHub (Sep 30, 2026).
Original GitHub issue: https://github.com/games-on-whales/wolf/issues/518

When a stream leaves a lobby while the game keeps running, Wolf's memory can grow by ~500 MB/s until the OOM killer takes it out, with gst_inter_pipe_ilistener_push_buffer: assertion 'GST_INTER_PIPE_IS_ILISTENER (self)' failed flooding the log. Rejoining that lobby then shows a frozen picture. The bug is in gst-interpipe; fix: games-on-whales/gst-interpipe#3

Setup

  • ghcr.io/games-on-whales/wolf:stable (a1edc1b), GStreamer 1.26.7, NVIDIA RTX 2080 SUPER, WOLF_USE_ZERO_COPY=FALSE, in a Proxmox LXC
  • Client: moonlight-web-stream v2.10.0, 1080p60 H.264

Steps

  1. Connect with moonlight-web and start Steam from Wolf UI (this creates a lobby).
  2. Close the browser tab instead of using Exit.
  3. About 10 s later Wolf logs the stream as over and its RSS starts climbing.

3 out of 3 times with moonlight-web. The desktop client's Ctrl+Alt+Shift+Q didn't trigger it, and neither does moonlight-web's Exit button.

Log

16:19:21.329  [LOBBY] Moonlight stream 1467…441 over, leaving lobby 921af6e4-…
16:19:21.329  [LOBBY] Session 1467…441 leaving lobby 921af6e4-…
ERROR interpipesink gstinterpipesink.c:1048:gst_inter_pipe_sink_add_listener:<1467…441_video> Failed to reconfigure
WARN  interpipe gstinterpipe.c:169:gst_inter_pipe_listen_node: Could not add listener interpipesrc_1467…441_video to node 1467…441_video
ERROR interpipesink gstinterpipesink.c:1104:gst_inter_pipe_sink_remove_listener:<921af6e4-…_video> Listener interpipesrc_1467…441_video is not registered in node 921af6e4-…_video
ERROR interpipesrc gstinterpipesrc.c:275:gst_inter_pipe_src_set_property:<interpipesrc_1467…441_video> Could not listen to node 1467…441_video
16:19:21.353  Stopped container: /Wolf-UI_1467…441
** CRITICAL **: gst_inter_pipe_ilistener_push_buffer: assertion 'GST_INTER_PIPE_IS_ILISTENER (self)' failed    (~100/s from here)
16:19:48      supervisord: exited: wolf (terminated by SIGKILL; not expected)    (memory cgroup oom_kill)

In another run: 1.1 GiB → 6.5 GiB in 11 s. Memory already lost stays lost until Wolf restarts; stopping the empty lobby through the API stops the growth.

What happens

leave_lobby() switches the stream's interpipesrc back to the session's own node while the stream's pipelines are going to EOS, and here the session's Wolf UI producer is being stopped at the same moment. The switch fails (Failed to reconfigure), and gst-interpipe's fallback leaves its global listeners table and the lobby node's table out of step. The lobby's interpipesink keeps the source after it's freed, so every frame is pushed to freed memory and the buffer ref taken for it is never released. On resume the new source has the same name, add_listener() keeps the stale entry as "already registered", and the new stream gets no frames.

The desktop client's quit is a clean pause, the Wolf UI producer stays up and the switch back succeeds. Closing a moonlight-web tab drops the connection late (when its WebRTC peer times out), which lands in the window.

With the fix

Same Wolf image, only libgstinterpipe.so rebuilt from the PR branch: leaving logs Dropping listener …, freed while still registered, no assertion flood, memory stays flat, and rejoining the lobby from Wolf UI works.

To try it before a new image:

FROM ghcr.io/games-on-whales/wolf:stable AS build
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates gcc git meson ninja-build pkg-config libglib2.0-dev
RUN git clone -b fix/stale-listeners https://github.com/gorylpe/gst-interpipe /src \
    && cd /src && meson setup build -Denable-gtk-doc=false -Dtests=disabled && ninja -C build

FROM ghcr.io/games-on-whales/wolf:stable
COPY --from=build /src/build/gst/interpipe/libgstinterpipe.so /usr/local/lib/x86_64-linux-gnu/gstreamer-1.0/libgstinterpipe.so

Possibly related: #364 (same assertion, but when sessions join a shared lobby).

Originally created by @gorylpe on GitHub (Sep 30, 2026). Original GitHub issue: https://github.com/games-on-whales/wolf/issues/518 When a stream leaves a lobby while the game keeps running, Wolf's memory can grow by ~500 MB/s until the OOM killer takes it out, with `gst_inter_pipe_ilistener_push_buffer: assertion 'GST_INTER_PIPE_IS_ILISTENER (self)' failed` flooding the log. Rejoining that lobby then shows a frozen picture. The bug is in gst-interpipe; fix: [games-on-whales/gst-interpipe#3](https://github.com/games-on-whales/gst-interpipe/pull/3) ## Setup - `ghcr.io/games-on-whales/wolf:stable` (a1edc1b), GStreamer 1.26.7, NVIDIA RTX 2080 SUPER, `WOLF_USE_ZERO_COPY=FALSE`, in a Proxmox LXC - Client: [moonlight-web-stream](https://github.com/MrCreativ3001/moonlight-web-stream) v2.10.0, 1080p60 H.264 ## Steps 1. Connect with moonlight-web and start Steam from Wolf UI (this creates a lobby). 2. Close the browser tab instead of using Exit. 3. About 10 s later Wolf logs the stream as over and its RSS starts climbing. 3 out of 3 times with moonlight-web. The desktop client's Ctrl+Alt+Shift+Q didn't trigger it, and neither does moonlight-web's Exit button. ## Log ``` 16:19:21.329 [LOBBY] Moonlight stream 1467…441 over, leaving lobby 921af6e4-… 16:19:21.329 [LOBBY] Session 1467…441 leaving lobby 921af6e4-… ERROR interpipesink gstinterpipesink.c:1048:gst_inter_pipe_sink_add_listener:<1467…441_video> Failed to reconfigure WARN interpipe gstinterpipe.c:169:gst_inter_pipe_listen_node: Could not add listener interpipesrc_1467…441_video to node 1467…441_video ERROR interpipesink gstinterpipesink.c:1104:gst_inter_pipe_sink_remove_listener:<921af6e4-…_video> Listener interpipesrc_1467…441_video is not registered in node 921af6e4-…_video ERROR interpipesrc gstinterpipesrc.c:275:gst_inter_pipe_src_set_property:<interpipesrc_1467…441_video> Could not listen to node 1467…441_video 16:19:21.353 Stopped container: /Wolf-UI_1467…441 ** CRITICAL **: gst_inter_pipe_ilistener_push_buffer: assertion 'GST_INTER_PIPE_IS_ILISTENER (self)' failed (~100/s from here) 16:19:48 supervisord: exited: wolf (terminated by SIGKILL; not expected) (memory cgroup oom_kill) ``` In another run: 1.1 GiB → 6.5 GiB in 11 s. Memory already lost stays lost until Wolf restarts; stopping the empty lobby through the API stops the growth. ## What happens `leave_lobby()` switches the stream's `interpipesrc` back to the session's own node while the stream's pipelines are going to EOS, and here the session's Wolf UI producer is being stopped at the same moment. The switch fails (`Failed to reconfigure`), and gst-interpipe's fallback leaves its global listeners table and the lobby node's table out of step. The lobby's `interpipesink` keeps the source after it's freed, so every frame is pushed to freed memory and the buffer ref taken for it is never released. On resume the new source has the same name, `add_listener()` keeps the stale entry as "already registered", and the new stream gets no frames. The desktop client's quit is a clean pause, the Wolf UI producer stays up and the switch back succeeds. Closing a moonlight-web tab drops the connection late (when its WebRTC peer times out), which lands in the window. ## With the fix Same Wolf image, only `libgstinterpipe.so` rebuilt from the PR branch: leaving logs `Dropping listener …, freed while still registered`, no assertion flood, memory stays flat, and rejoining the lobby from Wolf UI works. To try it before a new image: ```dockerfile FROM ghcr.io/games-on-whales/wolf:stable AS build RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates gcc git meson ninja-build pkg-config libglib2.0-dev RUN git clone -b fix/stale-listeners https://github.com/gorylpe/gst-interpipe /src \ && cd /src && meson setup build -Denable-gtk-doc=false -Dtests=disabled && ninja -C build FROM ghcr.io/games-on-whales/wolf:stable COPY --from=build /src/build/gst/interpipe/libgstinterpipe.so /usr/local/lib/x86_64-linux-gnu/gstreamer-1.0/libgstinterpipe.so ``` Possibly related: #364 (same assertion, but when sessions join a shared lobby).
Sign in to join this conversation.
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#314
No description provided.