From 2c636016b0f263399e3c351ffbab13d7ad1afe94 Mon Sep 17 00:00:00 2001 From: "Brandon McGinty (chatgpt)" Date: Sun, 9 Aug 2026 19:24:48 -0400 Subject: [PATCH] Report OpenAL lifecycle errors --- fix.txt | 2 +- gumble/gumbleopenal/stream.go | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/fix.txt b/fix.txt index bd85b61..6eecf3b 100644 --- a/fix.txt +++ b/fix.txt @@ -254,7 +254,7 @@ Priority 3: configuration, UI, and binding hardening vetted representation/pattern and re-run vet. Listener orientation uses a global tempSlice without synchronization; use a local fixed array. -33. OpenAL errors are mostly ignored +[x] 33. OpenAL errors are mostly ignored Files: gumble/gumbleopenal/stream.go, gumble/go-openal/openal/*.go Source/buffer/context/capture calls generally do not check AL/ALC errors, so invalid device/context/buffer operations become silent audio failure. diff --git a/gumble/gumbleopenal/stream.go b/gumble/gumbleopenal/stream.go index b08357c..92f8a8c 100644 --- a/gumble/gumbleopenal/stream.go +++ b/gumble/gumbleopenal/stream.go @@ -3,6 +3,7 @@ package gumbleopenal import ( "encoding/binary" "errors" + "fmt" "math" "runtime" "sync" @@ -110,6 +111,10 @@ func New(client *gumble.Client, inputDevice *string, outputDevice *string, test log.Error("OpenAL capture: failed to open device %q", devName) return nil, ErrInputDevice } + if err := idev.Err(); err != nil { + idev.CaptureCloseDevice() + return nil, fmt.Errorf("%w: %v", ErrInputDevice, err) + } log.Info("OpenAL capture: opened device %q format=%v channels=%d", devName, inputFormat, sourceChannels) outName := "" @@ -121,6 +126,11 @@ func New(client *gumble.Client, inputDevice *string, outputDevice *string, test idev.CaptureCloseDevice() return nil, ErrOutputDevice } + if err := odev.Err(); err != nil { + idev.CaptureCloseDevice() + odev.CloseDevice() + return nil, fmt.Errorf("%w: %v", ErrOutputDevice, err) + } if test { idev.CaptureCloseDevice() @@ -151,7 +161,11 @@ func New(client *gumble.Client, inputDevice *string, outputDevice *string, test } s.contextSink = s.deviceSink.CreateContext() if s.contextSink == nil { + err := s.deviceSink.Err() s.Destroy() + if err != nil { + return nil, fmt.Errorf("%w: %v", ErrOutputDevice, err) + } return nil, ErrOutputDevice } // OpenAL contexts are current to an OS thread. Move ownership to one @@ -334,6 +348,9 @@ func (s *Stream) StartSource(inputDevice *string) error { return ErrMic } s.deviceSource.CaptureStart() + if err := s.deviceSource.Err(); err != nil { + return fmt.Errorf("%w: %v", ErrMic, err) + } stop := make(chan bool) done := make(chan struct{}) s.sourceStop, s.sourceDone = stop, done @@ -357,6 +374,9 @@ func (s *Stream) StopSource() error { return ErrMic } s.deviceSource.CaptureStop() + if err := s.deviceSource.Err(); err != nil { + return fmt.Errorf("%w: %v", ErrMic, err) + } return nil }