Thread race in juce_VST_Wrapper.cpp?

Are hosts required to call setStateInformation on the message thread? If not I believe there are some variables that are accessed both from message thread and the thread that hosts calls setStateInformation on since juce_VST_Wrapper.cpp recevies calls from the message thread in timerCallback on line ~1092, and there for example chunkMemory.reset() is called, and at the same time chunkMemory.reset() is also called from handleSetData.

This post says that Protools does not call on message thread:

Below is a stacktrace when running BackgroundThreadStateTest from pluginval.

   WARNING: ThreadSanitizer: data race (pid=30699)
 Write of size 8 at 0x7b64001b0e30 by thread T8 (mutexes: write M479206114148257264):
#0 juce::MemoryBlock::reset() juce_MemoryBlock.cpp:145 (Digitone:x86_64+0x1022d5c)
#1 JuceVSTWrapper::handleSetData(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1870 (Digitone:x86_64+0x15a83)
#2 JuceVSTWrapper::dispatcher(int, JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1193 (Digitone:x86_64+0x13610)
#3 JuceVSTWrapper::dispatcherCB(Vst2::AEffect*, int, int, long long, void*, float) juce_VST_Wrapper.cpp:1235 (Digitone:x86_64+0xa31f)
#4 juce::VSTPluginInstance::dispatch(int, int, long long, void*, float) const juce_VSTPluginFormat.cpp:1728 (pluginval:x86_64+0x1000a23a9)
#5 juce::VSTPluginInstance::setChunkData(void const*, int, bool) juce_VSTPluginFormat.cpp:1959 (pluginval:x86_64+0x1000a5f4b)
#6 juce::VSTPluginInstance::loadFromFXBFile(void const*, unsigned long) juce_VSTPluginFormat.cpp:1817 (pluginval:x86_64+0x1000a4ce9)
#7 juce::VSTPluginInstance::setStateInformation(void const*, int) juce_VSTPluginFormat.cpp:1591 (pluginval:x86_64+0x1001294f5)
#8 BackgroundThreadStateTest::runTest(PluginTests&, juce::AudioPluginInstance&) BasicTests.cpp:438 (pluginval:x86_64+0x100070be5)
#9 PluginTests::testType(juce::PluginDescription const&) PluginTests.cpp:153 (pluginval:x86_64+0x100034f59)
#10 PluginTests::runTest() PluginTests.cpp:90 (pluginval:x86_64+0x100034102)
#11 juce::UnitTest::performTest(juce::UnitTestRunner*) juce_UnitTest.cpp:77 (pluginval:x86_64+0x10073c8bd)
#12 juce::UnitTestRunner::runTests(juce::Array<juce::UnitTest*, juce::DummyCriticalSection, 0> const&, long long) juce_UnitTest.cpp:165 (pluginval:x86_64+0x10073dd74)
#13 runTests(PluginTests&, std::__1::function<void (juce::String const&)>) Validator.cpp:106 (pluginval:x86_64+0x100052717)
#14 validate(juce::String const&, PluginTests::Options, std::__1::function<void (juce::String const&)>) Validator.cpp:123 (pluginval:x86_64+0x100051e81)
#15 ValidatorSlaveProcess::processRequest(juce::MemoryBlock) Validator.cpp:383 (pluginval:x86_64+0x10004fd98)
#16 ValidatorSlaveProcess::processRequests() Validator.cpp:352 (pluginval:x86_64+0x10004eaa2)
#17 ValidatorSlaveProcess::run() Validator.cpp:319 (pluginval:x86_64+0x10004b692)
#18 non-virtual thunk to ValidatorSlaveProcess::run() Validator.cpp (pluginval:x86_64+0x10004b8cc)
#19 juce::Thread::threadEntryPoint() juce_Thread.cpp:96 (pluginval:x86_64+0x10072f96c)
#20 juce::juce_threadEntryPoint(void*) juce_Thread.cpp:118 (pluginval:x86_64+0x100730188)
#21 threadEntryProc juce_posix_SharedCode.h:897 (pluginval:x86_64+0x1007833f9)

  Previous write of size 8 at 0x7b64001b0e30 by main thread:
[failed to restore the stack]

 Location is heap block of size 1120 at 0x7b64001b0d00 allocated by main thread:
#0 operator new(unsigned long) <null>:3733472 
(libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x4ec7b)
#1 (anonymous namespace)::pluginEntryPoint(long long (*)(Vst2::AEffect*, int, int, long long, void*, float)) juce_VST_Wrapper.cpp:2315 (Digitone:x86_64+0x7fa4)
#2 main_macho juce_VST_Wrapper.cpp:2360 (Digitone:x86_64+0x826c)
#3 juce::VSTPluginInstance::constructEffect(juce::ReferenceCountedObjectPtr<juce::ModuleHandle> const&) juce_VSTPluginFormat.cpp:2152 (pluginval:x86_64+0x10016282c)
#4 juce::VSTPluginInstance::create(juce::ReferenceCountedObjectPtr<juce::ModuleHandle> const&, double, int) juce_VSTPluginFormat.cpp:1142 (pluginval:x86_64+0x1000a3553)
#5 juce::VSTPluginFormat::createPluginInstance(juce::PluginDescription const&, double, int, void*, void (*)(void*, juce::AudioPluginInstance*, juce::String const&)) juce_VSTPluginFormat.cpp:3566 (pluginval:x86_64+0x1000a286d)
#6 juce::AudioPluginFormat::createPluginInstanceOnMessageThread(juce::PluginDescription const&, double, int, juce::AudioPluginFormat::InstantiationCompletionCallback*) juce_AudioPluginFormat.cpp:210 (pluginval:x86_64+0x10007c7e8)
#7 juce::AudioPluginFormat::createPluginInstanceAsync(juce::PluginDescription const&, double, int, juce::AudioPluginFormat::InstantiationCompletionCallback*)::InvokeOnMessageThread::messageCallback() juce_AudioPluginFormat.cpp:161 (pluginval:x86_64+0x1001396af)
#8 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:82 (pluginval:x86_64+0x1008adcc6)
#9 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:93 (pluginval:x86_64+0x1008adbe9)
#10 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:101 (pluginval:x86_64+0x1008ad9b8)
#11 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:3733472 (CoreFoundation:x86_64h+0x57682)
#12 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:262 (pluginval:x86_64+0x1008847bc)
#13 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:240 (pluginval:x86_64+0x1008841b5)
#14 main Main.cpp:183 (pluginval:x86_64+0x10000f64c)

 Mutex M479206114148257264 is already destroyed.

 Thread T8 (tid=204361, running) created by main thread at:
#0 pthread_create <null>:3733520 (libclang_rt.tsan_osx_dynamic.dylib:x86_64h+0x89dd)
#1 juce::Thread::launchThread() juce_posix_SharedCode.h:954 (pluginval:x86_64+0x1007303c9)
#2 juce::Thread::startThread() juce_Thread.cpp:130 (pluginval:x86_64+0x100730238)
#3 juce::Thread::startThread(int) juce_Thread.cpp:152 (pluginval:x86_64+0x10073070b)
#4 ValidatorSlaveProcess::ValidatorSlaveProcess() Validator.cpp:201 (pluginval:x86_64+0x10004b1a1)
#5 ValidatorSlaveProcess::ValidatorSlaveProcess() Validator.cpp:196 (pluginval:x86_64+0x10004acd8)
#6 ValidatorMasterProcess::launchInProcess() memory:3114 (pluginval:x86_64+0x10004767c)
#7 Validator::ensureConnection() Validator.cpp:640 (pluginval:x86_64+0x100045bc7)
#8 Validator::validate(juce::StringArray const&, PluginTests::Options) Validator.cpp:592 (pluginval:x86_64+0x1000451f5)
#9 CommandLineValidator::validate(juce::StringArray const&, PluginTests::Options, bool) CommandLine.cpp:102 (pluginval:x86_64+0x100008034)
#10 validate(CommandLineValidator&, juce::StringArray const&) CommandLine.cpp:270 (pluginval:x86_64+0x10000bba1)
#11 performCommandLine(CommandLineValidator&, juce::String const&) CommandLine.cpp:410 (pluginval:x86_64+0x10000a627)
#12 PluginValidatorApplication::handleAsyncUpdate() Main.cpp:177 (pluginval:x86_64+0x100012417)
#13 non-virtual thunk to PluginValidatorApplication::handleAsyncUpdate() Main.cpp (pluginval:x86_64+0x1000125dc)
#14 juce::AsyncUpdater::AsyncUpdaterMessage::messageCallback() juce_AsyncUpdater.cpp:34 (pluginval:x86_64+0x10089d803)
#15 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:82 (pluginval:x86_64+0x1008adcc6)
#16 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:93 (pluginval:x86_64+0x1008adbe9)
#17 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:101 (pluginval:x86_64+0x1008ad9b8)
#18 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:3733520 (CoreFoundation:x86_64h+0x57682)
#19 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:262 (pluginval:x86_64+0x1008847bc)
#20 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:240 (pluginval:x86_64+0x1008841b5)
#21 main Main.cpp:183 (pluginval:x86_64+0x10000f64c)

SUMMARY: ThreadSanitizer: data race juce_MemoryBlock.cpp:145 in juce::MemoryBlock::reset()
1 Like

Thank you for reporting.