mirror of https://github.com/jetkvm/kvm.git
Fix: prevent concurrent Opus decoder access during session transfers
During session transfers, multiple handleInputTrackForSession goroutines could call WriteMessage() concurrently on the shared inputSource, causing Opus SILK decoder state corruption and assertion failures. Added inputSourceMutex to serialize WriteMessage() calls and prevent race conditions in both input and output audio paths.
This commit is contained in:
parent
3121747712
commit
f6012e5c3f
10
audio.go
10
audio.go
|
|
@ -13,6 +13,8 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
audioMutex sync.Mutex
|
audioMutex sync.Mutex
|
||||||
|
setAudioTrackMutex sync.Mutex // Prevents concurrent setAudioTrack() calls
|
||||||
|
inputSourceMutex sync.Mutex // Serializes WriteMessage() calls to input source
|
||||||
outputSource audio.AudioSource
|
outputSource audio.AudioSource
|
||||||
inputSource atomic.Pointer[audio.AudioSource]
|
inputSource atomic.Pointer[audio.AudioSource]
|
||||||
outputRelay *audio.OutputRelay
|
outputRelay *audio.OutputRelay
|
||||||
|
|
@ -130,6 +132,10 @@ func onWebRTCDisconnect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func setAudioTrack(audioTrack *webrtc.TrackLocalStaticSample) {
|
func setAudioTrack(audioTrack *webrtc.TrackLocalStaticSample) {
|
||||||
|
// Prevent concurrent calls to avoid creating multiple relays
|
||||||
|
setAudioTrackMutex.Lock()
|
||||||
|
defer setAudioTrackMutex.Unlock()
|
||||||
|
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
currentAudioTrack = audioTrack
|
currentAudioTrack = audioTrack
|
||||||
oldRelay := outputRelay
|
oldRelay := outputRelay
|
||||||
|
|
@ -146,7 +152,6 @@ func setAudioTrack(audioTrack *webrtc.TrackLocalStaticSample) {
|
||||||
oldSource.Disconnect()
|
oldSource.Disconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new source and relay for the new track
|
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
if currentAudioTrack != nil && audioOutputEnabled.Load() {
|
if currentAudioTrack != nil && audioOutputEnabled.Load() {
|
||||||
alsaDevice := "hw:1,0"
|
alsaDevice := "hw:1,0"
|
||||||
|
|
@ -265,9 +270,12 @@ func handleInputTrackForSession(track *webrtc.TrackRemote) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Serialize WriteMessage() to prevent concurrent session handlers from corrupting Opus decoder
|
||||||
|
inputSourceMutex.Lock()
|
||||||
if err := (*source).WriteMessage(0, opusData); err != nil {
|
if err := (*source).WriteMessage(0, opusData); err != nil {
|
||||||
audioLogger.Warn().Err(err).Msg("failed to write audio message")
|
audioLogger.Warn().Err(err).Msg("failed to write audio message")
|
||||||
(*source).Disconnect()
|
(*source).Disconnect()
|
||||||
}
|
}
|
||||||
|
inputSourceMutex.Unlock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue