Tsan race in opengl after updating to JUCE 7

I get some race reports on our thread sanitizer builds:

WARNING: ThreadSanitizer: data race (pid=10274)
  Write of size 8 at 0x7b1400002e78 by main thread:
    #0 juce::OpenGLContext::NativeContext::setNominalVideoRefreshPeriodS(double) juce_OpenGL_osx.h:246 (Digitakt:x86_64+0x1de0b1c)
    #1 juce::OpenGLContext::CachedImage::updateScreen() juce_OpenGLContext.cpp:1023 (Digitakt:x86_64+0x1de0693)
    #2 juce::OpenGLContext::CachedImage::updateViewportSize() juce_OpenGLContext.cpp:430 (Digitakt:x86_64+0x1df9651)
    #3 juce::OpenGLContext::CachedImage::paint(juce::Graphics&) juce_OpenGLContext.cpp:207 (Digitakt:x86_64+0x1dd1d80)
    #4 juce::Component::paintWithinParentContext(juce::Graphics&) juce_Component.cpp:1992 (Digitakt:x86_64+0x9d1917)
    #5 juce::Component::paintComponentAndChildren(juce::Graphics&) juce_Component.cpp:2052 (Digitakt:x86_64+0x9d2538)
    #6 juce::Component::paintEntireComponent(juce::Graphics&, bool) juce_Component.cpp:2107 (Digitakt:x86_64+0x9d1e81)
    #7 juce::ComponentPeer::handlePaint(juce::LowLevelGraphicsContext&) juce_ComponentPeer.cpp:135 (Digitakt:x86_64+0xb279a0)
    #8 juce::NSViewComponentPeer::renderRect(CGContext*, CGRect, float) juce_mac_NSViewComponentPeer.mm:965 (Digitakt:x86_64+0xc9e7a9)
    #9 juce::NSViewComponentPeer::drawRectWithContext(CGContext*, CGRect) juce_mac_NSViewComponentPeer.mm:953 (Digitakt:x86_64+0xc9e602)
    #10 juce::NSViewComponentPeer::drawRect(CGRect) ...
ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:281 (pluginval:x86_64+0x1000e3298)
    #17 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:282 (pluginval:x86_64+0x1000e3198)
    #18 EditorTest::runTest(PluginTests&, juce::AudioPluginInstance&) BasicTests.cpp:106 (pluginval:x86_64+0x1000e2e92)
    #19 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:x86_64+0x100096e07)
    #20 decltype(std::__1::forward<PluginTests::testType(juce::PluginDescription const&)::$_1&>(fp)()) std::__1::__invoke<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) type_traits:3747 (pluginval:x86_64+0x100096cf0)
    #21 void std::__1::__invoke_void_return_wrapper<void>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) __functional_base:348 (pluginval:x86_64+0x100096c50)
    #22 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1553 (pluginval:x86_64+0x100096bf0)
    #23 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1727 (pluginval:x86_64+0x100094aff)
    #24 std::__1::__function::__value_func<void ()>::operator()() const functional:1880 (pluginval:x86_64+0x1000dd108)
    #25 std::__1::function<void ()>::operator()() const functional:2555 (pluginval:x86_64+0x1000dc988)
    #26 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:197 (pluginval:x86_64+0x100c8a24f)
    #27 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:81 (pluginval:x86_64+0x100c9e17b)
    #28 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:92 (pluginval:x86_64+0x100c9e0a9)
    #29 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:100 (pluginval:x86_64+0x100c9daab)
    #30 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:2 (CoreFoundation:x86_64+0x8166b)
    #31 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:x86_64+0x100c778b8)
    #32 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:x86_64+0x100c77638)
    #33 main Main.cpp:173 (pluginval:x86_64+0x10004446c)

  Previous read of size 8 at 0x7b1400002e78 by thread T33 (mutexes: write M328335389192389648):
    #0 juce::OpenGLContext::NativeContext::updateMinSwapTime() juce_OpenGL_osx.h:252 (Digitakt:x86_64+0x1de15eb)
    #1 juce::OpenGLContext::NativeContext::setSwapInterval(int) juce_OpenGL_osx.h:229 (Digitakt:x86_64+0x1d9b1d5)
    #2 juce::OpenGLContext::CachedImage::initialiseOnThread() juce_OpenGLContext.cpp:654 (Digitakt:x86_64+0x1dd7619)
    #3 juce::OpenGLContext::CachedImage::renderFrame(juce::MessageManager::Lock&) juce_OpenGLContext.cpp:317 (Digitakt:x86_64+0x1dd61a1)
    #4 juce::OpenGLContext::CachedImage::RenderThread::renderAll() juce_OpenGLContext.cpp:835 (Digitakt:x86_64+0x1dd5ac0)
    #5 juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()::operator()() const juce_OpenGLContext.cpp:925 (Digitakt:x86_64+0x1dd578d)
    #6 decltype(std::__1::forward<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>(fp)()) std::__1::__invoke<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&...) type_traits:3747 (Digitakt:x86_64+0x1dd5650)
    #7 void std::__1::__thread_execute<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:280 (Digitakt:x86_64+0x1dd54b8)
    #8 void* std::__1::__thread_proxy<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:291 (Digitakt:x86_64+0x1dd45b9)

  Location is heap block of size 72 at 0x7b1400002e40 allocated by main thread:
    #0 operator new(unsigned long) <null>:2 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x7801b)
    #1 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:144 (Digitakt:x86_64+0x1dd1171)
    #2 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:143 (Digitakt:x86_64+0x1dd0c58)
    #3 juce::OpenGLContext::Attachment::attach() juce_OpenGLContext.cpp:1184 (Digitakt:x86_64+0x1dd0483)
    #4 juce::OpenGLContext::Attachment::componentVisibilityChanged() juce_OpenGLContext.cpp:1135 (Digitakt:x86_64+0x1dd0972)
    #5 juce::ComponentMovementWatcher::componentVisibilityChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:120 (Digitakt:x86_64+0xa38590)
    #6 juce::Component::sendVisibilityChangeMessage()::$_3::operator()(juce::ComponentListener&) const juce_Component.cpp:613 (Digitakt:x86_64+0xd2451a)
    #7 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0> >::callChecked<juce::Component::sendVisibilityChangeMessage()::$_3, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::sendVisibilityChangeMessage()::$_3&&) juce_ListenerList.h:170 (Digitakt:x86_64+0x9c46fb)
    #8 juce::Component::sendVisibilityChangeMessage() juce_Component.cpp:613 (Digitakt:x86_64+0x9c4279)
    #9 juce::Component::setVisible(bool) juce_Component.cpp:591 (Digitakt:x86_64+0x9c3c07)
    #10 juce::attachComponentToWindowRefVST(juce::Component*, void*, bool) juce_VST_Wrapper.mm:176 (Digitakt:x86_64+0x40489)
    #11 JuceVSTWrapper::EditorCompWrapper::attachToHost(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1024 (Digitakt:x86_64+0x23aee)
    #12 JuceVSTWrapper::handleOpenEditor(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1638 (Digitakt:x86_64+0x1aca7)
    #13 JuceVSTWrapper::dispatcher(int, JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:907 (Digitakt:x86_64+0x18e27)
    #14 JuceVSTWrapper::dispatcherCB(Vst2::AEffect*, int, int, long long, void*, float) juce_VST_Wrapper.cpp:954 (Digitakt:x86_64+0xf136)
    #15 juce::VSTPluginInstance::dispatch(int, int, long long, void*, float) const juce_VSTPluginFormat.cpp:1744 (pluginval:x86_64+0x100157f0b)
    #16 juce::VSTPluginWindow::dispatch(int, int, int, void*, float) juce_VSTPluginFormat.cpp:3265 (pluginval:x86_64+0x100209a12)
...   
std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1727 (pluginval:x86_64+0x100094aff)
    #31 std::__1::__function::__value_func<void ()>::operator()() const functional:1880 (pluginval:x86_64+0x1000dd108)
    #32 std::__1::function<void ()>::operator()() const functional:2555 (pluginval:x86_64+0x1000dc988)
    #33 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:197 (pluginval:x86_64+0x100c8a24f)
    #34 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:81 (pluginval:x86_64+0x100c9e17b)
    #35 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:92 (pluginval:x86_64+0x100c9e0a9)
    #36 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:100 (pluginval:x86_64+0x100c9daab)
    #37 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:2 (CoreFoundation:x86_64+0x8166b)
    #38 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:x86_64+0x100c778b8)
    #39 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:x86_64+0x100c77638)
    #40 main Main.cpp:173 (pluginval:x86_64+0x10004446c)

  Mutex M328335389192389648 is already destroyed.

  Thread T33 (tid=9597987, running) created by main thread at:
    #0 pthread_create <null>:2 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2dabd)
    #1 std::__1::__libcpp_thread_create(_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:501 (Digitakt:x86_64+0x1dd44fe)
    #2 std::__1::thread::thread<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'(), void>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&) thread:307 (Digitakt:x86_64+0x1dd41b6)
    #3 std::__1::thread::thread<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'(), void>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&) thread:299 (Digitakt:x86_64+0x1dd3ad8)
    #4 juce::OpenGLContext::CachedImage::RenderThread::RenderThread() juce_OpenGLContext.cpp:922 (Digitakt:x86_64+0x1dd3954)
    #5 juce::OpenGLContext::CachedImage::RenderThread::RenderThread() juce_OpenGLContext.cpp:782 (Digitakt:x86_64+0x1dd2898)
    #6 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::initialise() juce_SharedResourcePointer.h:150 (Digitakt:x86_64+0x1dd238a)
    #7 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::SharedResourcePointer() juce_SharedResourcePointer.h:92 (Digitakt:x86_64+0x1dd2253)
    #8 juce::SharedResourcePointer<juce::OpenGLContext::CachedImage::RenderThread>::SharedResourcePointer() juce_SharedResourcePointer.h:91 (Digitakt:x86_64+0x1dd14e8)
    #9 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:139 (Digitakt:x86_64+0x1dd0e7e)
    #10 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:143 (Digitakt:x86_64+0x1dd0c58)
    #11 juce::OpenGLContext::Attachment::attach() juce_OpenGLContext.cpp:1184 (Digitakt:x86_64+0x1dd0483)
    #12 juce::OpenGLContext::Attachment::componentVisibilityChanged() juce_OpenGLContext.cpp:1135 (Digitakt:x86_64+0x1dd0972)
    #13 juce::ComponentMovementWatcher::componentVisibilityChanged(juce::Component&) juce_ComponentMovementWatcher.cpp:120 (Digitakt:x86_64+0xa38590)
    #14 juce::Component::sendVisibilityChangeMessage()::$_3::operator()(juce::ComponentListener&) const juce_Component.cpp:613 (Digitakt:x86_64+0xd2451a)
    #15 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0> >::callChecked<juce::Component::sendVisibilityChangeMessage()::$_3, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::sendVisibilityChangeMessage()::$_3&&) juce_ListenerList.h:170 (Digitakt:x86_64+0x9c46fb)
    #16 juce::Component::sendVisibilityChangeMessage() juce_Component.cpp:613 (Digitakt:x86_64+0x9c4279)
    #17 juce::Component::setVisible(bool) juce_Component.cpp:591 (Digitakt:x86_64+0x9c3c07)
    #18 juce::attachComponentToWindowRefVST(juce::Component*, void*, bool) juce_VST_Wrapper.mm:176 (Digitakt:x86_64+0x40489)
    #19 JuceVSTWrapper::EditorCompWrapper::attachToHost(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1024 (Digitakt:x86_64+0x23aee)
    #20 JuceVSTWrapper::handleOpenEditor(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1638 (Digitakt:x86_64+0x1aca7)
    #21 JuceVSTWrapper::dispatcher(int, JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:907 (Digitakt:x86_64+0x18e27)
    #22 JuceVSTWrapper::dispatcherCB(Vst2::AEffect*, int, int, long long, void*, float) juce_VST_Wrapper.cpp:954 (Digitakt:x86_64+0xf136)
    #23 juce::VSTPluginInstance::dispatch(int, int, long long, void*, float) const juce_VSTPluginFormat.cpp:1744 (pluginval:x86_64+0x100157f0b)
    #24 juce::VSTPluginWindow::dispatch(int, int, int, void*, float) juce_VSTPluginFormat.cpp:3265 (pluginval:x86_64+0x100209a12)
    #25 juce::VSTPluginWindow::openPluginWindow(void*) juce_VSTPluginFormat.cpp:3077 (pluginval:x86_64+0x10020d01b)
    #26 juce::VSTPluginWindow::visibilityChanged() juce_VSTPluginFormat.cpp:2856 (pluginval:x86_64+0x100209c17)
    #27 juce::VSTPluginWindow::parentHierarchyChanged() juce_VSTPluginFormat.cpp:2870 (pluginval:x86_64+0x100209c9f)
    #28 juce::Component::internalHierarchyChanged() juce_Component.cpp:1697 (pluginval:x86_64+0x100484417)
    #29 juce::Component::addToDesktop(int, void*) juce_Component.cpp:747 (pluginval:x86_64+0x100484f3c)
    #30 createAndShowEditorOnMessageThread(juce::AudioPluginInstance&) TestUtilities.h:152 (pluginval:x86_64+0x1000e34db)
    #31 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:281 (pluginval:x86_64+0x1000e3298)
    #32 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:282 (pluginval:x86_64+0x1000e3198)
    #33 EditorTest::runTest(PluginTests&, juce::AudioPluginInstance&) BasicTests.cpp:106 (pluginval:x86_64+0x1000e2e92)
    #34 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:x86_64+0x100096e07)
    #35 decltype(std::__1::forward<PluginTests::testType(juce::PluginDescription const&)::$_1&>(fp)()) std::__1::__invoke<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) type_traits:3747 (pluginval:x86_64+0x100096cf0)
    #36 void std::__1::__invoke_void_return_wrapper<void>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) __functional_base:348 (pluginval:x86_64+0x100096c50)
    #37 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1553 (pluginval:x86_64+0x100096bf0)
    #38 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1727 (pluginval:x86_64+0x100094aff)
    #39 std::__1::__function::__value_func<void ()>::operator()() const functional:1880 (pluginval:x86_64+0x1000dd108)
    #40 std::__1::function<void ()>::operator()() const functional:2555 (pluginval:x86_64+0x1000dc988)
    #41 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:197 (pluginval:x86_64+0x100c8a24f)
    #42 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:81 (pluginval:x86_64+0x100c9e17b)
    #43 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:92 (pluginval:x86_64+0x100c9e0a9)
    #44 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:100 (pluginval:x86_64+0x100c9daab)
    #45 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:2 (CoreFoundation:x86_64+0x8166b)
    #46 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:x86_64+0x100c778b8)
    #47 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:x86_64+0x100c77638)
    #48 main Main.cpp:173 (pluginval:x86_64+0x10004446c)

SUMMARY: ThreadSanitizer: data race juce_OpenGL_osx.h:246 in juce::OpenGLContext::NativeContext::setNominalVideoRefreshPeriodS(double)
==================
==================
WARNING: ThreadSanitizer: data race (pid=10274)
  Read of size 4 at 0x7b1400002e70 by main thread:
    #0 juce::OpenGLContext::NativeContext::updateMinSwapTime() juce_OpenGL_osx.h:252 (Digitakt:x86_64+0x1de15c9)
    #1 juce::OpenGLContext::NativeContext::setNominalVideoRefreshPeriodS(double) juce_OpenGL_osx.h:247 (Digitakt:x86_64+0x1de0b32)
    #2 juce::OpenGLContext::CachedImage::updateScreen() juce_OpenGLContext.cpp:1023 (Digitakt:x86_64+0x1de0693)
    #3 juce::OpenGLContext::CachedImage::updateViewportSize() juce_OpenGLContext.cpp:430 (Digitakt:x86_64+0x1df9651)
    #4 juce::OpenGLContext::CachedImage::paint(juce::Graphics&) juce_OpenGLContext.cpp:207 (Digitakt:x86_64+0x1dd1d80)
    #5 juce::Component::paintWithinParentContext(juce::Graphics&) juce_Component.cpp:1992 (Digitakt:x86_64+0x9d1917)
    #6 juce::Component::paintComponentAndChildren(juce::Graphics&) juce_Component.cpp:2052 (Digitakt:x86_64+0x9d2538)
    #7 juce::Component::paintEntireComponent(juce::Graphics&, bool) juce_Component.cpp:2107 (Digitakt:x86_64+0x9d1e81)
    #8 juce::ComponentPeer::handlePaint(juce::LowLevelGraphicsContext&) juce_ComponentPeer.cpp:135 (Digitakt:x86_64+0xb279a0)
    #9 juce::NSViewComponentPeer::renderRect(CGContext*, CGRect, float) juce_mac_NSViewComponentPeer.mm:965 (Digitakt:x86_64+0xc9e7a9)
    #10 juce::NSViewComponentPeer::drawRectWithContext(CGContext*, CGRect) juce_mac_NSViewComponentPeer.mm:953 (Digitakt:x86_64+0xc9e602)
    #11 juce::NSViewComponentPeer::drawRect(CGRect) juce_mac_NSViewComponentPeer.mm:902 (Digitakt:x86_64+0xca73ea)
    #12 void juce::JuceNSViewClass::callOnOwner<void (juce::NSViewComponentPeer::*)(CGRect), CGRect&>(objc_object*, void (juce::NSViewComponentPeer::*&&)(CGRect), CGRect&) juce_mac_NSViewComponentPeer.mm:2370 (Digitakt:x86_64+0xca72b6)
    #13 juce::JuceNSViewClass::JuceNSViewClass()::'lambda'(objc_object*, objc_selector*, CGRect)::operator()(objc_object*, objc_selector*, CGRect) const juce_mac_NSViewComponentPeer.mm:1956 (Digitakt:x86_64+0xca704b)
    #14 juce::JuceNSViewClass::JuceNSViewClass()::'lambda'(objc_object*, objc_selector*, CGRect)::__invoke(objc_object*, objc_selector*, CGRect) juce_mac_NSViewComponentPeer.mm:1956 (Digitakt:x86_64+0xca7125)
    #15 _NSViewDrawRect <null>:2 (AppKit:x86_64+0x1af46a)
    #16 createAndShowEditorOnMessageThread(juce::AudioPluginInstance&) TestUtilities.h:158 (pluginval:x86_64+0x1000e353a)
    #17 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:281 (pluginval:x86_64+0x1000e3298)
    #18 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:282 (pluginval:x86_64+0x1000e3198)
    #19 EditorTest::runTest(PluginTests&, juce::AudioPluginInstance&) BasicTests.cpp:106 (pluginval:x86_64+0x1000e2e92)
    #20 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:x86_64+0x100096e07)
    #21 decltype(std::__1::forward<PluginTests::testType(juce::PluginDescription const&)::$_1&>(fp)()) std::__1::__invoke<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) type_traits:3747 (pluginval:x86_64+0x100096cf0)
    #22 void std::__1::__invoke_void_return_wrapper<void>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) __functional_base:348 (pluginval:x86_64+0x100096c50)
    #23 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1553 (pluginval:x86_64+0x100096bf0)
    #24 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1727 (pluginval:x86_64+0x100094aff)
    #25 std::__1::__function::__value_func<void ()>::operator()() const functional:1880 (pluginval:x86_64+0x1000dd108)
    #26 std::__1::function<void ()>::operator()() const functional:2555 (pluginval:x86_64+0x1000dc988)
    #27 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:197 (pluginval:x86_64+0x100c8a24f)
    #28 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:81 (pluginval:x86_64+0x100c9e17b)
    #29 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:92 (pluginval:x86_64+0x100c9e0a9)
    #30 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:100 (pluginval:x86_64+0x100c9daab)
    #31 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:2 (CoreFoundation:x86_64+0x8166b)
    #32 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:x86_64+0x100c778b8)
    #33 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:x86_64+0x100c77638)
    #34 main Main.cpp:173 (pluginval:x86_64+0x10004446c)

  Previous write of size 4 at 0x7b1400002e70 by thread T33 (mutexes: write M328335389192389648):
    #0 juce::OpenGLContext::NativeContext::setSwapInterval(int) juce_OpenGL_osx.h:220 (Digitakt:x86_64+0x1d9b105)
    #1 juce::OpenGLContext::CachedImage::initialiseOnThread() juce_OpenGLContext.cpp:654 (Digitakt:x86_64+0x1dd7619)
    #2 juce::OpenGLContext::CachedImage::renderFrame(juce::MessageManager::Lock&) juce_OpenGLContext.cpp:317 (Digitakt:x86_64+0x1dd61a1)
    #3 juce::OpenGLContext::CachedImage::RenderThread::renderAll() juce_OpenGLContext.cpp:835 (Digitakt:x86_64+0x1dd5ac0)
    #4 juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()::operator()() const juce_OpenGLContext.cpp:925 (Digitakt:x86_64+0x1dd578d)
    #5 decltype(std::__1::forward<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>(fp)()) std::__1::__invoke<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&, juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&...) type_traits:3747 (Digitakt:x86_64+0x1dd5650)
    #6 void std::__1::__thread_execute<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:280 (Digitakt:x86_64+0x1dd54b8)
    #7 void* std::__1::__thread_proxy<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:291 (Digitakt:x86_64+0x1dd45b9)

  Location is heap block of size 72 at 0x7b1400002e40 allocated by main thread:
    #0 operator new(unsigned long) <null>:2 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x7801b)
    #1 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:144 (Digitakt:x86_64+0x1dd1171)
    #2 juce::OpenGLContext::CachedImage::CachedImage(juce::OpenGLContext&, juce::Component&, juce::OpenGLPixelFormat const&, void*) juce_OpenGLContext.cpp:143 (Digitakt:x86_64+0x1dd0c58)
    #3 juce::OpenGLContext::Attachment::attach() juce_OpenGLContext.cpp:1184 (Digitakt:x86_64+0x1dd0483)
    #4 juce::OpenGLContext::Attachment::componentVisibilityChanged() ...
JuceVSTWrapper::EditorCompWrapper::attachToHost(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1024 (Digitakt:x86_64+0x23aee)
    #12 JuceVSTWrapper::handleOpenEditor(JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:1638 (Digitakt:x86_64+0x1aca7)
    #13 JuceVSTWrapper::dispatcher(int, JuceVSTWrapper::VstOpCodeArguments) juce_VST_Wrapper.cpp:907 (Digitakt:x86_64+0x18e27)
    #14 JuceVSTWrapper::dispatcherCB(Vst2::AEffect*, int, int, long long, void*, float) juce_VST_Wrapper.cpp:954 (Digitakt:x86_64+0xf136)
    #15 juce::VSTPluginInstance::dispatch(int, int, long long, void*, float) const juce_VSTPluginFormat.cpp:1744 (pluginval:x86_64+0x100157f0b)
    #16 juce::VSTPluginWindow::dispatch(int, int, int, void*, float) juce_VSTPluginFormat.cpp:3265 (pluginval:x86_64+0x100209a12)
    #17 juce::VSTPluginWindow::openPluginWindow(void*) juce_VSTPluginFormat.cpp:3077 (pluginval:x86_64+0x10020d01b)
    #18 juce::VSTPluginWindow::visibilityChanged() juce_VSTPluginFormat.cpp:2856 (pluginval:x86_64+0x100209c17)
    #19 juce::VSTPluginWindow::parentHierarchyChanged() juce_VSTPluginFormat.cpp:2870 (pluginval:x86_64+0x100209c9f)
    #20 juce::Component::internalHierarchyChanged() juce_Component.cpp:1697 (pluginval:x86_64+0x100484417)
    #21 juce::Component::addToDesktop(int, void*) juce_Component.cpp:747 (pluginval:x86_64+0x100484f3c)
    #22 createAndShowEditorOnMessageThread(juce::AudioPluginInstance&) TestUtilities.h:152 (pluginval:x86_64+0x1000e34db)
    #23 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:281 (pluginval:x86_64+0x1000e3298)
    #24 ScopedEditorShower::ScopedEditorShower(juce::AudioPluginInstance&) TestUtilities.h:282 (pluginval:x86_64+0x1000e3198)
    #25 EditorTest::runTest(PluginTests&, juce::AudioPluginInstance&) BasicTests.cpp:106 (pluginval:x86_64+0x1000e2e92)
    #26 PluginTests::testType(juce::PluginDescription const&)::$_1::operator()() PluginTests.cpp:197 (pluginval:x86_64+0x100096e07)
    #27 decltype(std::__1::forward<PluginTests::testType(juce::PluginDescription const&)::$_1&>(fp)()) std::__1::__invoke<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) type_traits:3747 (pluginval:x86_64+0x100096cf0)
    #28 void std::__1::__invoke_void_return_wrapper<void>::__call<PluginTests::testType(juce::PluginDescription const&)::$_1&>(PluginTests::testType(juce::PluginDescription const&)::$_1&) __functional_base:348 (pluginval:x86_64+0x100096c50)
    #29 std::__1::__function::__alloc_func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1553 (pluginval:x86_64+0x100096bf0)
    #30 std::__1::__function::__func<PluginTests::testType(juce::PluginDescription const&)::$_1, std::__1::allocator<PluginTests::testType(juce::PluginDescription const&)::$_1>, void ()>::operator()() functional:1727 (pluginval:x86_64+0x100094aff)
    #31 std::__1::__function::__value_func<void ()>::operator()() const functional:1880 (pluginval:x86_64+0x1000dd108)
    #32 std::__1::function<void ()>::operator()() const functional:2555 (pluginval:x86_64+0x1000dc988)
    #33 juce::MessageManager::callAsync(std::__1::function<void ()>)::AsyncCallInvoker::messageCallback() juce_MessageManager.cpp:197 (pluginval:x86_64+0x100c8a24f)
    #34 juce::MessageQueue::deliverNextMessage() juce_osx_MessageQueue.h:81 (pluginval:x86_64+0x100c9e17b)
    #35 juce::MessageQueue::runLoopCallback() juce_osx_MessageQueue.h:92 (pluginval:x86_64+0x100c9e0a9)
    #36 juce::MessageQueue::runLoopSourceCallback(void*) juce_osx_MessageQueue.h:100 (pluginval:x86_64+0x100c9daab)
    #37 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ <null>:2 (CoreFoundation:x86_64+0x8166b)
    #38 juce::JUCEApplicationBase::main() juce_ApplicationBase.cpp:265 (pluginval:x86_64+0x100c778b8)
    #39 juce::JUCEApplicationBase::main(int, char const**) juce_ApplicationBase.cpp:243 (pluginval:x86_64+0x100c77638)
    #40 main Main.cpp:173 (pluginval:x86_64+0x10004446c)

  Mutex M328335389192389648 is already destroyed.

  Thread T33 (tid=9597987, running) created by main thread at:
    #0 pthread_create <null>:2 (libclang_rt.tsan_osx_dynamic.dylib:x86_64+0x2dabd)
    #1 std::__1::__libcpp_thread_create(_opaque_pthread_t**, void* (*)(void*), void*) __threading_support:501 (Digitakt:x86_64+0x1dd44fe)
    #2 std::__1::thread::thread<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'(), void>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&) thread:307 (Digitakt:x86_64+0x1dd41b6)
    #3 std::__1::thread::thread<juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'(), void>(juce::OpenGLContext::CachedImage::RenderThread::thread::'lambda'()&&) thread:299 (Digitakt:x86_64+0x1dd3ad8)
    #4 juce::OpenGLContext::CachedImage::RenderThread::RenderThread() juce_OpenGLContext.cpp:922 (Digitakt:x86_64+0x1dd3954)
    #5 juce::OpenGLContext::CachedImage::RenderThread::RenderThread() juce_OpenGLContext.cpp:782 (Digitakt:x86_64+0x1dd2898)
    #6 
...
SUMMARY: ThreadSanitizer: data race juce_OpenGL_osx.h:252 in juce::OpenGLContext::NativeContext::updateMinSwapTime()

Fixed it by changing some members to atomic:

    std::atomic<int> numFramesPerSwap = 0;
    std::atomic<double> videoRefreshPeriodS = 1.0 / 60.0;

Also needed to update a jassert:

        jassert (isPositiveAndBelow (numFramesPerSwap.load(), 2));

Hope this helps! :pray:

It would be helpful to know the following:

  • What JUCE version are you using? Is the issue present on develop?
  • How are you triggering the fault? Do you have a minimal test case that demonstrates the problem?

I wasn’t able to reproduce this bug, but I think I can see how the issue might be triggered in rare cases. I’ve pushed a potential fix here:

Please try updating to the latest version of JUCE and let me know if the issue is still present for you.