Data race in MessageManager::Lock after updating to JUCE 7.0.9

After JUCE has been updated to 7.0.9 (from 7.0.7) I get a warning from the thread sanitizer that there’s a data race in juce::MessageManager::Lock. See the following report:

WARNING: ThreadSanitizer: data race (pid=53429)
  Write of size 1 at 0x00010b70aab9 by main thread (mutexes: write M0):
    #0 juce::MessageManager::Lock::setAcquired(bool) const juce_MessageManager.cpp:438 (Plugin:arm64+0x17373a4)
    #1 juce::MessageManager::Lock::abort() const juce_MessageManager.cpp:430 (Plugin:arm64+0x1737300)
    #2 juce::OpenGLContext::CachedImage::RenderThread::abortLock() juce_OpenGLContext.cpp:771 (Plugin:arm64+0x1ab4374)
    #3 juce::OpenGLContext::CachedImage::RenderThread::remove(juce::OpenGLContext::CachedImage*) juce_OpenGLContext.cpp:753 (Plugin:arm64+0x1ab41cc)
    #4 juce::OpenGLContext::CachedImage::pause() juce_OpenGLContext.cpp:187 (Plugin:arm64+0x1ab2c8c)
    #5 juce::OpenGLContext::CachedImage::stop() juce_OpenGLContext.cpp:181 (Plugin:arm64+0x1ab2a4c)
    #6 juce::OpenGLContext::CachedImage::releaseResources() juce_OpenGLContext.cpp:244 (Plugin:arm64+0x1aa04f0)
    #7 juce::detail::ComponentHelpers::releaseAllCachedImageResources(juce::Component&) juce_ComponentHelpers.h:230 (Plugin:arm64+0xe0cdb8)
    #8 juce::detail::ComponentHelpers::releaseAllCachedImageResources(juce::Component&) juce_ComponentHelpers.h:233 (Plugin:arm64+0xe0ce20)
    #9 juce::Component::removeFromDesktop() juce_Component.cpp:434 (Plugin:arm64+0xe0c018)
    #10 juce::detail::VSTWindowUtilities::detachComponentFromWindowRefVST(juce::Component*, void*) juce_VSTWindowUtilities.h:69 (Plugin:arm64+0x116df4)
    #11 juce::JuceVST3EditController::JuceVST3Editor::removed() juce_audio_plugin_client_VST3.cpp:1841 (Plugin:arm64+0x105ea8)
    #12 non-virtual thunk to juce::JuceVST3EditController::JuceVST3Editor::removed() juce_audio_plugin_client_VST3.cpp (Plugin:arm64+0x107224)
    #13 juce::VST3PluginWindow::~VST3PluginWindow() juce_VST3PluginFormat.cpp:1538 (pluginval:arm64+0x1002ce6b8)
    #14 juce::VST3PluginWindow::~VST3PluginWindow() juce_VST3PluginFormat.cpp:1529 (pluginval:arm64+0x1002c6aac)
    #15 juce::VST3PluginWindow::~VST3PluginWindow() juce_VST3PluginFormat.cpp:1529 (pluginval:arm64+0x1002c6af4)
    #16 std::__1::default_delete<juce::AudioProcessorEditor>::operator()[abi:v160006](juce::AudioProcessorEditor*) const unique_ptr.h:65 (pluginval:arm64+0x1000c1a4c)
    #17 std::__1::unique_ptr<juce::AudioProcessorEditor, std::__1::default_delete<juce::AudioProcessorEditor>>::reset[abi:v160006](juce::AudioProcessorEditor*) unique_ptr.h:297 (pluginval:arm64+0x1000c15dc)
    #18 deleteEditorOnMessageThread(std::__1::unique_ptr<juce::AudioProcessorEditor, std::__1::default_delete<juce::AudioProcessorEditor>>) TestUtilities.h:180 (pluginval:arm64+0x1000c4ef4)
    #19 ScopedEditorShower::~ScopedEditorShower() TestUtilities.h:287 (pluginval:arm64+0x1000c4e64)
    #20 ScopedEditorShower::~ScopedEditorShower() TestUtilities.h:286 (pluginval:arm64+0x1000c1184)
    #21 EditorStressTest::runTest(PluginTests&, juce::AudioPluginInstance&) EditorTests.cpp:44 (pluginval:arm64+0x1000ecca4)
    #22 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:arm64+0x10008129c)
    #23 decltype(std::declval<PluginTests::testType(juce::PluginDescription const&)::$_1&>()()) std::__1::__invoke[abi:v160006]<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) invoke.h:394 (pluginval:arm64+0x1000811d4)
    #24 void std::__1::__invoke_void_return_wrapper<void, true>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) invoke.h:487 (pluginval:arm64+0x100081138)
    #25 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()[abi:v160006]() function.h:185 (pluginval:arm64+0x1000810e4)
    #26 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() function.h:356 (pluginval:arm64+0x10007f394)
    #27 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const function.h:510 (pluginval:arm64+0x1000bbfb0)
    #28 std::__1::function<void ()>::operator()() const function.h:1156 (pluginval:arm64+0x1000bb9ec)
    #29 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:200 (pluginval:arm64+0x100bd730c)
    #30 juce::MessageQueue::deliverNextMessage() juce_MessageQueue_mac.h:81 (pluginval:arm64+0x100bed66c)
    #31 juce::MessageQueue::runLoopCallback() juce_MessageQueue_mac.h:92 (pluginval:arm64+0x100bed59c)
    #32 juce::MessageQueue::runLoopSourceCallback(void*) juce_MessageQueue_mac.h:100 (pluginval:arm64+0x100bed054)
    #33 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:130682500 (CoreFoundation:arm64e+0x7dd24)
    #34 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:arm64+0x100bc59a4)
    #35 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:arm64+0x100bc5748)
    #36 main Main.cpp:173 (pluginval:arm64+0x10003cba0)

  Previous write of size 1 at 0x00010b70aab9 by thread T127 (mutexes: write M1, write M2, write M3):
    #0 juce::MessageManager::Lock::exit() const juce_MessageManager.cpp:425 (Plugin:arm64+0x1736748)
    #1 juce::GenericScopedTryLock<juce::MessageManager::Lock>::~GenericScopedTryLock() juce_ScopedLock.h:228 (Plugin:arm64+0x1aa7fbc)
    #2 juce::GenericScopedTryLock<juce::MessageManager::Lock>::~GenericScopedTryLock() juce_ScopedLock.h:228 (Plugin:arm64+0x1aa7f44)
    #3 std::__1::__optional_destruct_base<juce::GenericScopedTryLock<juce::MessageManager::Lock>, false>::reset[abi:v160006]() optional:274 (Plugin:arm64+0x1aa4e24)
    #4 juce::OpenGLContext::CachedImage::renderFrame(juce::MessageManager::Lock&) juce_OpenGLContext.cpp:417 (Plugin:arm64+0x1aa355c)
    #5 juce::OpenGLContext::CachedImage::RenderThread::renderAll() juce_OpenGLContext.cpp:787 (Plugin:arm64+0x1aa2b6c)
    #6 juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()::operator()() const juce_OpenGLContext.cpp:876 (Plugin:arm64+0x1aa28a0)
    #7 decltype(std::declval<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>()()) std::__1::__invoke[abi:v160006]<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&...) invoke.h:394 (Plugin:arm64+0x1aa27b0)
    #8 void std::__1::__thread_execute[abi:v160006]<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>&, std::__1::__tuple_indices<>) thread:288 (Plugin:arm64+0x1aa275c)
    #9 void* std::__1::__thread_proxy[abi:v160006]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>>(std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>) thread:299 (Plugin:arm64+0x1aa21f0)

  Location is heap block of size 472 at 0x00010b70aa00 allocated by main thread:
    #0 operator new(unsigned long) <null>:130682500 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x84420)
    #1 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::initialise() juce_SharedResourcePointer.h:150 (Plugin:arm64+0x1aa0818)
    #2 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::SharedResourcePointer() juce_SharedResourcePointer.h:92 (Plugin:arm64+0x1aa06f8)
    #3 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::SharedResourcePointer() juce_SharedResourcePointer.h:91 (Plugin:arm64+0x1a9fa24)
    #4 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:139 (Plugin:arm64+0x1a9f550)
    #5 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:143 (Plugin:arm64+0x1a9f388)
    #6 juce::OpenGLContext::Attachment::attach() juce_OpenGLContext.cpp:1172 (Plugin:arm64+0x1a9ebf8)
    #7 juce::OpenGLContext::Attachment::componentVisibilityChanged() juce_OpenGLContext.cpp:1123 (Plugin:arm64+0x1a9f088)
    #8 juce::ComponentMovementWatcher::componentVisibilityChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:120 (Plugin:arm64+0xe5ad6c)
    #9 juce::Component::sendVisibilityChangeMessage()::$_12::operator()(juce::ComponentListener&) const juce_Component.cpp:281 (Plugin:arm64+0x1170e38)
    #10 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0>>::callChecked<juce::Component::sendVisibilityChangeMessage()::$_12, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::sendVisibilityChangeMessage()::$_12&&) juce_ListenerList.h:182 (Plugin:arm64+0xe0d30c)
    #11 juce::Component::sendVisibilityChangeMessage() juce_Component.cpp:281 (Plugin:arm64+0xe0cf84)
    #12 juce::Component::setVisible(bool) juce_Component.cpp:259 (Plugin:arm64+0xe0ca70)
    #13 juce::detail::VSTWindowUtilities::attachComponentToWindowRefVST(juce::Component*, int, void*) juce_VSTWindowUtilities.h:56 (Plugin:arm64+0x116c50)
    #14 juce::JuceVST3EditController::JuceVST3Editor::attached(void*, char const*) juce_audio_plugin_client_VST3.cpp:1819 (Plugin:arm64+0x105d74)
    #15 non-virtual thunk to juce::JuceVST3EditController::JuceVST3Editor::attached(void*, char const*) juce_audio_plugin_client_VST3.cpp (Plugin:arm64+0x1071c4)
    #16 juce::VST3PluginWindow::attachPluginWindow() juce_VST3PluginFormat.cpp:1739 (pluginval:arm64+0x1002ceeb4)
    #17 juce::VST3PluginWindow::componentVisibilityChanged() juce_VST3PluginFormat.cpp:1657 (pluginval:arm64+0x1002c7484)
    #18 non-virtual thunk to juce::VST3PluginWindow::componentVisibilityChanged() juce_VST3PluginFormat.cpp (pluginval:arm64+0x1002c7a28)
    #19 juce::ComponentMovementWatcher::componentVisibilityChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:120 (pluginval:arm64+0x1004f2bcc)
    #20 juce::ComponentMovementWatcher::componentParentHierarchyChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:73 (pluginval:arm64+0x1004f25e8)
    #21 juce::Component::internalHierarchyChanged()::$_15::operator()(juce::ComponentListener&) const juce_Component.cpp:1370 (pluginval:arm64+0x100823f74)
    #22 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0>>::callChecked<juce::Component::internalHierarchyChanged()::$_15, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::internalHierarchyChanged()::$_15&&) juce_ListenerList.h:182 (pluginval:arm64+0x1004ab050)
    #23 juce::Component::internalHierarchyChanged() juce_Component.cpp:1370 (pluginval:arm64+0x1004a2ba8)
    #24 juce::Component::addToDesktop(int, void*) juce_Component.cpp:415 (pluginval:arm64+0x1004a34c4)
    #25 createAndShowEditorOnMessageThread(juce::AudioPluginInstance&) TestUtilities.h:152 (pluginval:arm64+0x1000c138c)
    #26 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:281 (pluginval:arm64+0x1000c11dc)
    #27 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:282 (pluginval:arm64+0x1000c10d0)
    #28 EditorStressTest::runTest(PluginTests&, juce::AudioPluginInstance&) EditorTests.cpp:43 (pluginval:arm64+0x1000ecc98)
    #29 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:arm64+0x10008129c)
    #30 decltype(std::declval<PluginTests::testType(juce::PluginDescription const&)::$_1&>()()) std::__1::__invoke[abi:v160006]<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) invoke.h:394 (pluginval:arm64+0x1000811d4)
    #31 void std::__1::__invoke_void_return_wrapper<void, true>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) invoke.h:487 (pluginval:arm64+0x100081138)
    #32 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()[abi:v160006]() function.h:185 (pluginval:arm64+0x1000810e4)
    #33 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() function.h:356 (pluginval:arm64+0x10007f394)
    #34 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const function.h:510 (pluginval:arm64+0x1000bbfb0)
    #35 std::__1::function<void ()>::operator()() const function.h:1156 (pluginval:arm64+0x1000bb9ec)
    #36 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:200 (pluginval:arm64+0x100bd730c)
    #37 juce::MessageQueue::deliverNextMessage() juce_MessageQueue_mac.h:81 (pluginval:arm64+0x100bed66c)
    #38 juce::MessageQueue::runLoopCallback() juce_MessageQueue_mac.h:92 (pluginval:arm64+0x100bed59c)
    #39 juce::MessageQueue::runLoopSourceCallback(void*) juce_MessageQueue_mac.h:100 (pluginval:arm64+0x100bed054)
    #40 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:130682500 (CoreFoundation:arm64e+0x7dd24)
    #41 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:arm64+0x100bc59a4)
    #42 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:arm64+0x100bc5748)
    #43 main Main.cpp:173 (pluginval:arm64+0x10003cba0)

  Thread T127 (tid=835965, running) created by main thread at:
    #0 pthread_create <null>:130682500 (libclang_rt.tsan_osx_dynamic.dylib:arm64e+0x3062c)
    #1 std::__1::__libcpp_thread_create[abi:v160006](_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:378 (Plugin:arm64+0xc57288)
    #2 std::__1::thread::thread<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'(), void>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&) thread:315 (Plugin:arm64+0x1aa1fd4)
    #3 std::__1::thread::thread<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'(), void>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&) thread:307 (Plugin:arm64+0x1aa1b40)
    #4 juce::OpenGLContext::CachedImage::RenderThread::RenderThread() juce_OpenGLContext.cpp:873 (Plugin:arm64+0x1aa19e4)
    #5 juce::OpenGLContext::CachedImage::RenderThread::RenderThread() juce_OpenGLContext.cpp:734 (Plugin:arm64+0x1aa0d5c)
    #6 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::initialise() juce_SharedResourcePointer.h:150 (Plugin:arm64+0x1aa0838)
    #7 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::SharedResourcePointer() juce_SharedResourcePointer.h:92 (Plugin:arm64+0x1aa06f8)
    #8 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::SharedResourcePointer() juce_SharedResourcePointer.h:91 (Plugin:arm64+0x1a9fa24)
    #9 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:139 (Plugin:arm64+0x1a9f550)
    #10 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:143 (Plugin:arm64+0x1a9f388)
    #11 juce::OpenGLContext::Attachment::attach() juce_OpenGLContext.cpp:1172 (Plugin:arm64+0x1a9ebf8)
    #12 juce::OpenGLContext::Attachment::componentVisibilityChanged() juce_OpenGLContext.cpp:1123 (Plugin:arm64+0x1a9f088)
    #13 juce::ComponentMovementWatcher::componentVisibilityChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:120 (Plugin:arm64+0xe5ad6c)
    #14 juce::Component::sendVisibilityChangeMessage()::$_12::operator()(juce::ComponentListener&) const juce_Component.cpp:281 (Plugin:arm64+0x1170e38)
    #15 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0>>::callChecked<juce::Component::sendVisibilityChangeMessage()::$_12, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::sendVisibilityChangeMessage()::$_12&&) juce_ListenerList.h:182 (Plugin:arm64+0xe0d30c)
    #16 juce::Component::sendVisibilityChangeMessage() juce_Component.cpp:281 (Plugin:arm64+0xe0cf84)
    #17 juce::Component::setVisible(bool) juce_Component.cpp:259 (Plugin:arm64+0xe0ca70)
    #18 juce::detail::VSTWindowUtilities::attachComponentToWindowRefVST(juce::Component*, int, void*) juce_VSTWindowUtilities.h:56 (Plugin:arm64+0x116c50)
    #19 juce::JuceVST3EditController::JuceVST3Editor::attached(void*, char const*) juce_audio_plugin_client_VST3.cpp:1819 (Plugin:arm64+0x105d74)
    #20 non-virtual thunk to juce::JuceVST3EditController::JuceVST3Editor::attached(void*, char const*) juce_audio_plugin_client_VST3.cpp (Plugin:arm64+0x1071c4)
    #21 juce::VST3PluginWindow::attachPluginWindow() juce_VST3PluginFormat.cpp:1739 (pluginval:arm64+0x1002ceeb4)
    #22 juce::VST3PluginWindow::componentVisibilityChanged() juce_VST3PluginFormat.cpp:1657 (pluginval:arm64+0x1002c7484)
    #23 non-virtual thunk to juce::VST3PluginWindow::componentVisibilityChanged() juce_VST3PluginFormat.cpp (pluginval:arm64+0x1002c7a28)
    #24 juce::ComponentMovementWatcher::componentVisibilityChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:120 (pluginval:arm64+0x1004f2bcc)
    #25 juce::ComponentMovementWatcher::componentParentHierarchyChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:73 (pluginval:arm64+0x1004f25e8)
    #26 juce::Component::internalHierarchyChanged()::$_15::operator()(juce::ComponentListener&) const juce_Component.cpp:1370 (pluginval:arm64+0x100823f74)
    #27 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0>>::callChecked<juce::Component::internalHierarchyChanged()::$_15, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::internalHierarchyChanged()::$_15&&) juce_ListenerList.h:182 (pluginval:arm64+0x1004ab050)
    #28 juce::Component::internalHierarchyChanged() juce_Component.cpp:1370 (pluginval:arm64+0x1004a2ba8)
    #29 juce::Component::addToDesktop(int, void*) juce_Component.cpp:415 (pluginval:arm64+0x1004a34c4)
    #30 createAndShowEditorOnMessageThread(juce::AudioPluginInstance&) TestUtilities.h:152 (pluginval:arm64+0x1000c138c)
    #31 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:281 (pluginval:arm64+0x1000c11dc)
    #32 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:282 (pluginval:arm64+0x1000c10d0)
    #33 EditorStressTest::runTest(PluginTests&, juce::AudioPluginInstance&) EditorTests.cpp:43 (pluginval:arm64+0x1000ecc98)
    #34 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:arm64+0x10008129c)
    #35 decltype(std::declval<PluginTests::testType(juce::PluginDescription const&)::$_1&>()()) std::__1::__invoke[abi:v160006]<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) invoke.h:394 (pluginval:arm64+0x1000811d4)
    #36 void std::__1::__invoke_void_return_wrapper<void, true>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) invoke.h:487 (pluginval:arm64+0x100081138)
    #37 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()[abi:v160006]() function.h:185 (pluginval:arm64+0x1000810e4)
    #38 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() function.h:356 (pluginval:arm64+0x10007f394)
    #39 std::__1::__function::__value_func<void ()>::operator()[abi:v160006]() const function.h:510 (pluginval:arm64+0x1000bbfb0)
    #40 std::__1::function<void ()>::operator()() const function.h:1156 (pluginval:arm64+0x1000bb9ec)
    #41 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:200 (pluginval:arm64+0x100bd730c)
    #42 juce::MessageQueue::deliverNextMessage() juce_MessageQueue_mac.h:81 (pluginval:arm64+0x100bed66c)
    #43 juce::MessageQueue::runLoopCallback() juce_MessageQueue_mac.h:92 (pluginval:arm64+0x100bed59c)
    #44 juce::MessageQueue::runLoopSourceCallback(void*) juce_MessageQueue_mac.h:100 (pluginval:arm64+0x100bed054)
    #45 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:130682500 (CoreFoundation:arm64e+0x7dd24)
    #46 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:arm64+0x100bc59a4)
    #47 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:arm64+0x100bc5748)
    #48 main Main.cpp:173 (pluginval:arm64+0x10003cba0)

SUMMARY: ThreadSanitizer: data race juce_MessageManager.cpp:438 in juce::MessageManager::Lock::setAcquired(bool) const

Can someone in the JUCE development team please have a look at this issue? :pray:

I’ll take a look. On the one hand fixing this looks relatively simple (thanks for the detailed stack trace), on the other I think there might be some more underlying issues with the MM::Lock so excuse me if this takes a little while.

Hey! Any update on this? I looked at the commits on develop but could not see anything related :slight_smile:

Friendly bump :slight_smile:

@anthony-nicholls:

Could it be that the variable aquired needs to be protected in the end of MessageManager::Lock::exit() (earlier in the same method it is accessed under a lock).

diff --git a/modules/juce_events/messages/juce_MessageManager.cpp b/modules/juce_events/messages/juce_MessageManager.cpp
index cd24761a9f..2d12dfd00b 100644
--- a/modules/juce_events/messages/juce_MessageManager.cpp
+++ b/modules/juce_events/messages/juce_MessageManager.cpp
@@ -422,6 +422,7 @@ void MessageManager::Lock::exit() const noexcept

     blockingMessage->stopWaiting();
     blockingMessage = nullptr;
+    const std::scoped_lock lock { mutex };
     acquired = false;
 }

With the above change the TSAN reports goes away.