Thread sanitizer is reporting a data race when switching the sample rate of a running audio device. Sometimes the application crashes with a sefault.
Environment:
macOS 14.6.1 (23G93)
JUCE 8.0.6
Steps to reproduce:
- Start an audio device using
juce::AudioDeviceManager - While processing, switch the sample rate of the device using
juce::AudioDeviceSettingsPanel
Report from TSAN:
==================
WARNING: ThreadSanitizer: data race (pid=71223)
Write of size 8 at 0x00016fa28f18 by main thread:
#0 juce::HeapBlock<unsigned int, false>::HeapBlock() juce_HeapBlock.h:371 (RAVENNAKIT JUCE Demo:arm64+0x1001b30a4)
#1 juce::HeapBlock<unsigned int, false>::HeapBlock() juce_HeapBlock.h:112 (RAVENNAKIT JUCE Demo:arm64+0x1001143d8)
#2 juce::BigInteger::BigInteger(juce::BigInteger const&) juce_BigInteger.cpp:115 (RAVENNAKIT JUCE Demo:arm64+0x100114b0c)
#3 juce::BigInteger::BigInteger(juce::BigInteger const&) juce_BigInteger.cpp:119 (RAVENNAKIT JUCE Demo:arm64+0x100114f04)
#4 auto juce::CoreAudioClasses::CoreAudioInternal::getWithDefault<juce::BigInteger const>(std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioInternal::Stream, std::__1::unique_ptr::default_delete<std::__1::unique_ptr::default_delete>> const&, juce::BigInteger const std::__1::unique_ptr::default_delete::*)::'lambda'(std::__1::unique_ptr::default_delete&)::operator()('lambda'(std::__1::unique_ptr::default_delete&)) const juce_CoreAudio_mac.cpp:1038 (RAVENNAKIT JUCE Demo:arm64+0x10147b1cc)
#5 std::__1 juce::CoreAudioClasses::CoreAudioInternal::getWithDefault<auto juce::CoreAudioClasses::CoreAudioInternal::getWithDefault<juce::BigInteger const>(std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioInternal::Stream, std::__1::unique_ptr::default_delete<std::__1::unique_ptr::default_delete>> const&, juce::BigInteger const std::__1::unique_ptr::default_delete::*)::'lambda'(std::__1::unique_ptr::default_delete&)>(juce::BigInteger const, juce::BigInteger const std::__1::unique_ptr::default_delete::*&&) juce_CoreAudio_mac.cpp:1032 (RAVENNAKIT JUCE Demo:arm64+0x10147b118)
#6 auto juce::CoreAudioClasses::CoreAudioInternal::getWithDefault<juce::BigInteger const>(std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioInternal::Stream, std::__1::unique_ptr::default_delete<std::__1::unique_ptr::default_delete>> const&, juce::BigInteger const std::__1::unique_ptr::default_delete::*) juce_CoreAudio_mac.cpp:1038 (RAVENNAKIT JUCE Demo:arm64+0x10147b080)
#7 juce::CoreAudioClasses::CoreAudioInternal::getActiveChannels(std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioInternal::Stream, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioInternal::Stream>> const&) juce_CoreAudio_mac.cpp:1046 (RAVENNAKIT JUCE Demo:arm64+0x10146f400)
#8 juce::CoreAudioClasses::CoreAudioIODevice::getActiveOutputChannels() const juce_CoreAudio_mac.cpp:1321 (RAVENNAKIT JUCE Demo:arm64+0x101466c84)
#9 juce::CoreAudioClasses::AudioIODeviceCombiner::DeviceWrapper::getActiveChannels() const juce_CoreAudio_mac.cpp:2001 (RAVENNAKIT JUCE Demo:arm64+0x101483d60)
#10 juce::CoreAudioClasses::AudioIODeviceCombiner::getActiveOutputChannels() const juce_CoreAudio_mac.cpp:1491 (RAVENNAKIT JUCE Demo:arm64+0x101481388)
#11 juce::AudioDeviceManager::updateCurrentSetup() juce_AudioDeviceManager.cpp:189 (RAVENNAKIT JUCE Demo:arm64+0x10143bda0)
#12 juce::AudioDeviceManager::setAudioDeviceSetup(juce::AudioDeviceManager::AudioDeviceSetup const&, bool) juce_AudioDeviceManager.cpp:824 (RAVENNAKIT JUCE Demo:arm64+0x10143edd4)
#13 juce::AudioDeviceSettingsPanel::updateConfig(bool, bool, bool, bool) juce_AudioDeviceSelectorComponent.cpp:452 (RAVENNAKIT JUCE Demo:arm64+0x10108bae0)
#14 juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()::operator()() const juce_AudioDeviceSelectorComponent.cpp:782 (RAVENNAKIT JUCE Demo:arm64+0x10109e378)
#15 decltype(std::declval<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()&>()()) std::__1::__invoke[abi:ne180100]<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()&>(juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()&) invoke.h:344 (RAVENNAKIT JUCE Demo:arm64+0x10109e2fc)
#16 void std::__1::__invoke_void_return_wrapper<void, true>::__call[abi:ne180100]<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()&>(juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()&) invoke.h:419 (RAVENNAKIT JUCE Demo:arm64+0x10109e260)
#17 std::__1::__function::__alloc_func<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'(), std::__1::allocator<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()>, void ()>::operator()[abi:ne180100]() function.h:169 (RAVENNAKIT JUCE Demo:arm64+0x10109e20c)
#18 std::__1::__function::__func<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'(), std::__1::allocator<juce::AudioDeviceSettingsPanel::updateSampleRateComboBox(juce::AudioIODevice*)::'lambda'()>, void ()>::operator()() function.h:311 (RAVENNAKIT JUCE Demo:arm64+0x10109c15c)
#19 std::__1::__function::__value_func<void ()>::operator()[abi:ne180100]() const function.h:428 (RAVENNAKIT JUCE Demo:arm64+0x100068e74)
#20 std::__1::function<void ()>::operator()() const function.h:981 (RAVENNAKIT JUCE Demo:arm64+0x1000689ec)
#21 void juce::NullCheckedInvocation::invoke<std::__1::function<void ()>&>(std::__1::function<void ()>&) juce_Functional.h:71 (RAVENNAKIT JUCE Demo:arm64+0x100387bd4)
#22 juce::ComboBox::handleAsyncUpdate() juce_ComboBox.cpp:637 (RAVENNAKIT JUCE Demo:arm64+0x100486c98)
#23 non-virtual thunk to juce::ComboBox::handleAsyncUpdate() juce_ComboBox.cpp (RAVENNAKIT JUCE Demo:arm64+0x100486df8)
#24 juce::AsyncUpdater::AsyncUpdaterMessage::messageCallback() juce_AsyncUpdater.cpp:46 (RAVENNAKIT JUCE Demo:arm64+0x100fb4f28)
#25 juce::MessageQueue::deliverNextMessage() juce_MessageQueue_mac.h:93 (RAVENNAKIT JUCE Demo:arm64+0x100fe0cd0)
#26 juce::MessageQueue::runLoopCallback() juce_MessageQueue_mac.h:104 (RAVENNAKIT JUCE Demo:arm64+0x100fe0c00)
#27 juce::MessageQueue::runLoopSourceCallback(void*) juce_MessageQueue_mac.h:112 (RAVENNAKIT JUCE Demo:arm64+0x100fe06cc)
#28 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:130030144 (CoreFoundation:arm64e+0x7e4d4)
#29 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:277 (RAVENNAKIT JUCE Demo:arm64+0x100f9ffd0)
#30 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:255 (RAVENNAKIT JUCE Demo:arm64+0x100f9fd7c)
#31 main MainApplication.cpp:173 (RAVENNAKIT JUCE Demo:arm64+0x10000dfb4)
Previous read of size 8 at 0x00016fa28f18 by thread T59 (mutexes: write M0):
#0 juce::CoreAudioClasses::AudioIODeviceCombiner::shutdown(juce::String const&) juce_CoreAudio_mac.cpp:1752 (RAVENNAKIT JUCE Demo:arm64+0x10148e498)
#1 juce::CoreAudioClasses::AudioIODeviceCombiner::stop() juce_CoreAudio_mac.cpp:1695 (RAVENNAKIT JUCE Demo:arm64+0x101481124)
#2 juce::CoreAudioClasses::AudioIODeviceCombiner::close() juce_CoreAudio_mac.cpp:1583 (RAVENNAKIT JUCE Demo:arm64+0x101480cec)
#3 juce::CoreAudioClasses::AudioIODeviceCombiner::restartAsync() juce_CoreAudio_mac.cpp:1647 (RAVENNAKIT JUCE Demo:arm64+0x101481664)
#4 non-virtual thunk to juce::CoreAudioClasses::AudioIODeviceCombiner::restartAsync() juce_CoreAudio_mac.cpp (RAVENNAKIT JUCE Demo:arm64+0x1014817f8)
#5 juce::CoreAudioClasses::CoreAudioIODevice::restart() juce_CoreAudio_mac.cpp:1376 (RAVENNAKIT JUCE Demo:arm64+0x10147b8bc)
#6 juce::CoreAudioClasses::CoreAudioInternal::deviceRequestedRestart() juce_CoreAudio_mac.cpp:857 (RAVENNAKIT JUCE Demo:arm64+0x10147b560)
#7 juce::CoreAudioClasses::CoreAudioInternal::deviceListenerProc(unsigned int, unsigned int, AudioObjectPropertyAddress const*, void*) juce_CoreAudio_mac.cpp:1194 (RAVENNAKIT JUCE Demo:arm64+0x10146881c)
#8 HALObject::PropertiesChanged(unsigned int, AudioObjectPropertyAddress const*) <null>:130030224 (CoreAudio:arm64e+0x269b8c)
#9 _dispatch_client_callout <null>:126121008 (libdispatch.dylib:arm64e+0x43e4)
Location is stack of main thread.
Mutex M0 (0x000109c0c118) created at:
#0 pthread_mutex_init <null>:134225072 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x3181c)
#1 juce::CriticalSection::CriticalSection() juce_SharedCode_posix.h:46 (RAVENNAKIT JUCE Demo:arm64+0x10012cbfc)
#2 juce::CriticalSection::CriticalSection() juce_SharedCode_posix.h:39 (RAVENNAKIT JUCE Demo:arm64+0x1000fb048)
#3 juce::CoreAudioClasses::AudioIODeviceCombiner::AudioIODeviceCombiner(juce::String const&, juce::CoreAudioClasses::CoreAudioIODeviceType*, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>&&, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>&&) juce_CoreAudio_mac.cpp:1461 (RAVENNAKIT JUCE Demo:arm64+0x10147fd48)
#4 juce::CoreAudioClasses::AudioIODeviceCombiner::AudioIODeviceCombiner(juce::String const&, juce::CoreAudioClasses::CoreAudioIODeviceType*, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>&&, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>&&) juce_CoreAudio_mac.cpp:1470 (RAVENNAKIT JUCE Demo:arm64+0x10147fab4)
#5 std::__1::__unique_if<juce::CoreAudioClasses::AudioIODeviceCombiner>::__unique_single std::__1::make_unique[abi:ne180100]<juce::CoreAudioClasses::AudioIODeviceCombiner, juce::String&, juce::CoreAudioClasses::CoreAudioIODeviceType*, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>>(juce::String&, juce::CoreAudioClasses::CoreAudioIODeviceType*&&, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>&&, std::__1::unique_ptr<juce::CoreAudioClasses::CoreAudioIODevice, std::__1::default_delete<juce::CoreAudioClasses::CoreAudioIODevice>>&&) unique_ptr.h:597 (RAVENNAKIT JUCE Demo:arm64+0x101465658)
#6 juce::CoreAudioClasses::CoreAudioIODeviceType::createDevice(juce::String const&, juce::String const&) juce_CoreAudio_mac.cpp:2262 (RAVENNAKIT JUCE Demo:arm64+0x10145ee8c)
#7 juce::AudioDeviceManager::setAudioDeviceSetup(juce::AudioDeviceManager::AudioDeviceSetup const&, bool) juce_AudioDeviceManager.cpp:774 (RAVENNAKIT JUCE Demo:arm64+0x10143e9e8)
#8 juce::AudioDeviceManager::initialiseDefault(juce::String const&, juce::AudioDeviceManager::AudioDeviceSetup const*) juce_AudioDeviceManager.cpp:400 (RAVENNAKIT JUCE Demo:arm64+0x10143cd4c)
#9 juce::AudioDeviceManager::initialise(int, int, juce::XmlElement const*, bool, juce::String const&, juce::AudioDeviceManager::AudioDeviceSetup const*) juce_AudioDeviceManager.cpp:322 (RAVENNAKIT JUCE Demo:arm64+0x10143de50)
#10 MainApplication::initialise(juce::String const&) MainApplication.cpp:98 (RAVENNAKIT JUCE Demo:arm64+0x10000b60c)
#11 juce::JUCEApplicationBase::initialiseApp() juce_ApplicationBase.cpp:312 (RAVENNAKIT JUCE Demo:arm64+0x100fa06a4)
#12 juce::JUCEApplication::initialiseApp() juce_Application.cpp:97 (RAVENNAKIT JUCE Demo:arm64+0x100382ad0)
#13 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:271 (RAVENNAKIT JUCE Demo:arm64+0x100f9ff80)
#14 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:255 (RAVENNAKIT JUCE Demo:arm64+0x100f9fd7c)
#15 main MainApplication.cpp:173 (RAVENNAKIT JUCE Demo:arm64+0x10000dfb4)
Thread T59 (tid=5395881, running) is a GCD worker thread
SUMMARY: ThreadSanitizer: data race juce_HeapBlock.h:371 in juce::HeapBlock<unsigned int, false>::HeapBlock()
