fix(audio): add proper locking for config cache updates

Add mutex locking around config cache expiration checks to prevent race conditions. The cache now properly checks initialization status before attempting updates.
This commit is contained in:
Alex P 2025-09-03 17:08:19 +00:00
parent a557987629
commit a741f05829
2 changed files with 72 additions and 8 deletions

View File

@ -865,7 +865,15 @@ func cgoAudioReadEncode(buf []byte) (int, error) {
// Fast path: Use AudioConfigCache to avoid GetConfig() in hot path
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}
@ -933,7 +941,15 @@ func cgoAudioDecodeWrite(buf []byte) (n int, err error) {
// Fast validation with AudioConfigCache
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}
@ -1092,7 +1108,15 @@ func ReadEncodeWithPooledBuffer() ([]byte, int, error) {
// Get cached config
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}
@ -1131,7 +1155,15 @@ func DecodeWriteWithPooledBuffer(data []byte) (int, error) {
// Get cached config
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}
@ -1158,7 +1190,15 @@ func BatchReadEncode(batchSize int) ([][]byte, error) {
// Get cached config
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}
@ -1237,7 +1277,15 @@ func BatchDecodeWrite(frames [][]byte) error {
// Get cached config
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}
@ -1312,7 +1360,15 @@ func cgoAudioDecodeWriteWithBuffers(opusData []byte, pcmBuffer []byte) (int, err
// Get cached config
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}

View File

@ -514,7 +514,15 @@ func (ais *AudioInputServer) processOpusFrame(data []byte) error {
// Get cached config for optimal performance
cache := GetCachedConfig()
// Only update cache if expired - avoid unnecessary overhead
if time.Since(cache.lastUpdate) > cache.cacheExpiry {
// Use proper locking to avoid race condition
if cache.initialized.Load() {
cache.mutex.RLock()
cacheExpired := time.Since(cache.lastUpdate) > cache.cacheExpiry
cache.mutex.RUnlock()
if cacheExpired {
cache.Update()
}
} else {
cache.Update()
}