From cdf6c332a6b347eea32eeb645f5ae031edafac0c Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 5 May 2017 15:42:22 -0400 Subject: [PATCH] prevent overflow of local injectors buffer --- libraries/audio-client/src/AudioClient.cpp | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index fb0220c24d..f61429812f 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1097,26 +1097,26 @@ void AudioClient::handleRecordedAudioInput(const QByteArray& audio) { } void AudioClient::prepareLocalAudioInjectors() { - if (_outputPeriod == 0) { - return; - } - - int bufferCapacity = _localInjectorsStream.getSampleCapacity(); - if (_localToOutputResampler) { - // avoid overwriting the buffer, - // instead of failing on writes because the buffer is used as a lock-free pipe - bufferCapacity -= - _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL) * - AudioConstants::STEREO; - bufferCapacity += 1; - } - int samplesNeeded = std::numeric_limits::max(); while (samplesNeeded > 0) { - // lock for every write to avoid locking out the device callback - // this lock is intentional - the buffer is only lock-free in its use in the device callback + // unlock between every write to allow device switching Lock lock(_localAudioMutex); + // in case of a device switch, consider bufferCapacity volatile across iterations + if (_outputPeriod == 0) { + return; + } + + int bufferCapacity = _localInjectorsStream.getSampleCapacity(); + if (_localToOutputResampler) { + // avoid overwriting the buffer, + // instead of failing on writes because the buffer is used as a lock-free pipe + bufferCapacity -= + _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL) * + AudioConstants::STEREO; + bufferCapacity += 1; + } + samplesNeeded = bufferCapacity - _localSamplesAvailable.load(std::memory_order_relaxed); if (samplesNeeded <= 0) { break;