mirror of
https://github.com/games-on-whales/gst-interpipe.git
synced 2026-10-15 12:51:56 +00:00
[PR #3] Drop freed interpipesrc listeners from nodes #3
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
games-on-whales/gst-interpipe#3
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/gst-interpipe/pull/3
Author: @gorylpe
Created: 9/30/2026
Status: 🔄 Open
Base:
master← Head:fix/stale-listeners📝 Commits (1)
757a441Drop freed interpipesrc listeners from nodes📊 Changes
6 files changed (+119 additions, -2 deletions)
View changed files
📝
gst/interpipe/gstinterpipe.c(+32 -0)📝
gst/interpipe/gstinterpipe.h(+9 -0)📝
gst/interpipe/gstinterpipeinode.c(+13 -0)📝
gst/interpipe/gstinterpipeinode.h(+15 -0)📝
gst/interpipe/gstinterpipesink.c(+38 -2)📝
gst/interpipe/gstinterpipesrc.c(+12 -0)📄 Description
When a
listen-toswitch races aninterpipesrc's teardown, the source can stay registered on a node after it is freed. The node then pushes every buffer to freed memory:gst_inter_pipe_ilistener_push_buffer()fails its type check and the ref taken ingst_inter_pipe_sink_push_to_listener()is never released. With raw 1080p60 video that's ~500 MB/s until the OOM killer steps in. A second effect: when the stream resumes, its new source has the same name,add_listener()keeps the stale entry as "already registered", and the resumed stream freezes.Reproducing with Wolf
ghcr.io/games-on-whales/wolf:stable(a1edc1b), GStreamer 1.26.7, NVIDIA legacy pipeline (WOLF_USE_ZERO_COPY=FALSE)Reproduced 3 of 3 times this way. Log from one of them (Wolf timestamps, UTC):
Wolf's
leave_lobby()switches the stream'sinterpipesrcback to the session's own node while the stream's pipelines are going to EOS. The switch fails (Failed to reconfigure), and the fallback ingst_inter_pipe_src_listen_node()leaves the global listeners table and the lobby node's table out of step. After that nothing removes the source from the lobby's node, not even when the source is freed. In another run, measured: 1.1 GiB → 6.5 GiB in 11 s.The desktop Moonlight client didn't trigger it (Ctrl+Alt+Shift+Q): that is a clean pause, the session's own producer stays up and the switch back succeeds. Closing a moonlight-web tab drops the connection late, when its WebRTC peer times out, while Wolf stops the session's Wolf UI producer at the same moment (
Stopped containerabove), so the switch lands on a producer that is being torn down. moonlight-web's Exit button stops cleanly and doesn't hit it either. It's a timing window, not something specific to moonlight-web.Possibly the same bug as games-on-whales/wolf#364 (Wolf crashing when sessions join a lobby): the reports there show the same
GST_INTER_PIPE_IS_ILISTENERassertions and, in one trace,malloc(): unaligned tcache chunk detectedright after a producer switch.Change
interpipesrcremoves itself ondispose. The newgst_inter_pipe_forget_listener()drops its listeners-table entry and asks every node, through a newforget_listenervfunc onGstInterPipeINode, to drop that exact object. A different listener registered under the same name is kept. The node list is copied first, so no node lock is taken while holdingnodes_mutex.interpipesink'sadd_listener()replaces the entry when a different object registers under a taken name, instead of keeping the stale one.Testing
libgstinterpipe.sorebuilt from this branch: closing the tab now logsDropping listener …, freed while still registered, there's no assertion flood, memory stays flat, and rejoining the lobby from Wolf UI streams again.meson test, built against the GStreamer in the Wolf image).🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.