release the audio stream a reconnect replaces

connect assigned b.Stream without releasing the stream already there, and
OnDisconnect started a reconnect loop unconditionally, so two connects could
race to install a stream. The loser was simply overwritten.

An overwritten stream is never destroyed, so it keeps its OpenAL device, its
render thread, and its entry in the shared audio listener list, which only
Destroy removes. It therefore stays subscribed for the life of the process
and every later audio packet from every user is dispatched to it as well: a
goroutine, a packet queue and a set of playback buffers per orphan, per
user. The file playback stream and the tone test saver were replaced the
same way.

Release whatever is being replaced, and allow only one reconnect loop at a
time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Brandon McGinty
2026-08-24 12:32:06 -04:00
co-authored by Claude Opus 5
parent da1c6bdc26
commit 77fad24560
2 changed files with 40 additions and 1 deletions
+2
View File
@@ -91,6 +91,8 @@ type Barnard struct {
reconnectStop chan struct{}
reconnectStopOnce sync.Once
reconnectMutex sync.Mutex
reconnecting bool
}
// cleanupConnectionAudio releases connection-owned audio resources before a