From 3faf7c0a184ca58d154a6dcfd2dc5df431396e1b Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 14 Jun 2026 12:33:23 -0400 Subject: [PATCH] fix(audio): serialize malgo device initialization --- internal/audio/malgo/playback.go | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/internal/audio/malgo/playback.go b/internal/audio/malgo/playback.go index 7384d80..be087ca 100644 --- a/internal/audio/malgo/playback.go +++ b/internal/audio/malgo/playback.go @@ -58,7 +58,13 @@ type AudioPlayer struct { volume atomic.Uint32 mutex sync.RWMutex deviceMutex sync.Mutex - closed bool + // deviceInitMutex serializes malgo.InitDevice calls against the shared + // context. Some host backends (notably PulseAudio) can abort the process + // when multiple goroutines enter ma_device_init concurrently on the same + // context, before Go can receive an ordinary error and skip device-free + // tests. + deviceInitMutex sync.Mutex + closed bool // contextInitOnce gates the lazy malgo.InitContext allocation in // PlaySoundWithContext. Two concurrent first-Play goroutines used to both // observe p.context==nil and both call NewContext(), leaking the loser's @@ -353,8 +359,12 @@ func (p *AudioPlayer) PlaySoundWithContext(ctx context.Context, soundID string) Data: onSamples, } - // Create and start device + // Create device. InitDevice touches shared C-side context state; serialize + // that narrow critical section while allowing playback callbacks to run + // concurrently after devices are initialized. + p.deviceInitMutex.Lock() device, err := malgo.InitDevice(p.context.GetContext().Context, deviceConfig, deviceCallbacks) + p.deviceInitMutex.Unlock() if err != nil { slog.Error("failed to initialize playback device", "sound_id", soundID, "error", err) return fmt.Errorf("failed to initialize playback device: %w", err) @@ -557,4 +567,4 @@ func applyVolumeToSamples(samples []byte, format malgo.FormatType, volume float3 default: slog.Warn("volume adjustment not implemented for format", "format", format) } -} \ No newline at end of file +}