mirror of https://github.com/jetkvm/kvm.git
fix: prevent audio disconnect from blocking new WebRTC sessions
When an old connection closed while a new one started, the audio cleanup would hold audioMutex for up to 37 seconds during CGO disconnect calls, blocking the new session from initializing. Use capture-clear-release pattern to minimize mutex hold time: - Capture references to sources/relays while holding mutex - Clear globals immediately so new sessions can proceed - Release mutex before calling blocking Stop/Disconnect operations This eliminates the 37-second hang during connection transitions.
This commit is contained in:
parent
b9705f4bac
commit
9e95cc3f8a
80
audio.go
80
audio.go
|
|
@ -78,41 +78,31 @@ func startAudio() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopOutputLocked stops output audio (assumes mutex is held)
|
|
||||||
func stopOutputLocked() {
|
|
||||||
if outputRelay != nil {
|
|
||||||
outputRelay.Stop()
|
|
||||||
outputRelay = nil
|
|
||||||
}
|
|
||||||
if outputSource != nil {
|
|
||||||
outputSource.Disconnect()
|
|
||||||
outputSource = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stopInputLocked stops input audio (assumes mutex is held)
|
|
||||||
func stopInputLocked() {
|
|
||||||
if inputRelay != nil {
|
|
||||||
inputRelay.Stop()
|
|
||||||
inputRelay = nil
|
|
||||||
}
|
|
||||||
if inputSource != nil {
|
|
||||||
inputSource.Disconnect()
|
|
||||||
inputSource = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stopAudioLocked stops all audio (assumes mutex is held)
|
|
||||||
func stopAudioLocked() {
|
|
||||||
stopOutputLocked()
|
|
||||||
stopInputLocked()
|
|
||||||
}
|
|
||||||
|
|
||||||
// stopAudio stops all audio
|
|
||||||
func stopAudio() {
|
func stopAudio() {
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
defer audioMutex.Unlock()
|
outRelay := outputRelay
|
||||||
stopAudioLocked()
|
outSource := outputSource
|
||||||
|
inRelay := inputRelay
|
||||||
|
inSource := inputSource
|
||||||
|
outputRelay = nil
|
||||||
|
outputSource = nil
|
||||||
|
inputRelay = nil
|
||||||
|
inputSource = nil
|
||||||
|
audioMutex.Unlock()
|
||||||
|
|
||||||
|
// Disconnect outside mutex to avoid blocking new sessions during CGO calls
|
||||||
|
if outRelay != nil {
|
||||||
|
outRelay.Stop()
|
||||||
|
}
|
||||||
|
if outSource != nil {
|
||||||
|
outSource.Disconnect()
|
||||||
|
}
|
||||||
|
if inRelay != nil {
|
||||||
|
inRelay.Stop()
|
||||||
|
}
|
||||||
|
if inSource != nil {
|
||||||
|
inSource.Disconnect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func onWebRTCConnect() {
|
func onWebRTCConnect() {
|
||||||
|
|
@ -169,8 +159,18 @@ func SetAudioOutputEnabled(enabled bool) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
stopOutputLocked()
|
outRelay := outputRelay
|
||||||
|
outSource := outputSource
|
||||||
|
outputRelay = nil
|
||||||
|
outputSource = nil
|
||||||
audioMutex.Unlock()
|
audioMutex.Unlock()
|
||||||
|
|
||||||
|
if outRelay != nil {
|
||||||
|
outRelay.Stop()
|
||||||
|
}
|
||||||
|
if outSource != nil {
|
||||||
|
outSource.Disconnect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -188,8 +188,18 @@ func SetAudioInputEnabled(enabled bool) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
stopInputLocked()
|
inRelay := inputRelay
|
||||||
|
inSource := inputSource
|
||||||
|
inputRelay = nil
|
||||||
|
inputSource = nil
|
||||||
audioMutex.Unlock()
|
audioMutex.Unlock()
|
||||||
|
|
||||||
|
if inRelay != nil {
|
||||||
|
inRelay.Stop()
|
||||||
|
}
|
||||||
|
if inSource != nil {
|
||||||
|
inSource.Disconnect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
13
jsonrpc.go
13
jsonrpc.go
|
|
@ -894,11 +894,20 @@ func rpcGetUsbDevices() (usbgadget.Devices, error) {
|
||||||
func updateUsbRelatedConfig(wasAudioEnabled bool) error {
|
func updateUsbRelatedConfig(wasAudioEnabled bool) error {
|
||||||
ensureConfigLoaded()
|
ensureConfigLoaded()
|
||||||
|
|
||||||
// Stop input audio before USB reconfiguration (input uses USB)
|
|
||||||
audioMutex.Lock()
|
audioMutex.Lock()
|
||||||
stopInputLocked()
|
inRelay := inputRelay
|
||||||
|
inSource := inputSource
|
||||||
|
inputRelay = nil
|
||||||
|
inputSource = nil
|
||||||
audioMutex.Unlock()
|
audioMutex.Unlock()
|
||||||
|
|
||||||
|
if inRelay != nil {
|
||||||
|
inRelay.Stop()
|
||||||
|
}
|
||||||
|
if inSource != nil {
|
||||||
|
inSource.Disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
if err := gadget.UpdateGadgetConfig(); err != nil {
|
if err := gadget.UpdateGadgetConfig(); err != nil {
|
||||||
return fmt.Errorf("failed to write gadget config: %w", err)
|
return fmt.Errorf("failed to write gadget config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue