We’ve had a number of reports of a plugin crashing on load. It seems to only happen on some Windows systems, across various DAWs (Ableton, Studio One, FL, Pro Tools, Reaper). JUCE version is 7.0.12.
I can’t reproduce it. I managed to get a .dmp file from the Ableton crash logs with debug symbols.
It looks like it’s triggered when trying to lock a mutex.
This is the exception:
Unhandled exception at 0x00007FFC43AE3020 (MSVCP140.dll) in Live_12.0.10_2024-06-21_518b0e8f66_2024_07_01__19_44_34.dmp: 0xC0000005: Access violation reading location 0x0000000000000000.
This is the stack trace:
MSVCP140.dll!mtx_do_lock(_Mtx_internal_imp_t * mtx, const xtime * target) Line 103
at d:\a01\_work\2\s\src\vctools\crt\github\stl\src\mutex.cpp(103)
[Inline Frame] MyCoolPlugin.vst3!std::_Mutex_base::lock() Line 52
at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\mutex(52)
[Inline Frame] MyCoolPlugin.vst3!std::lock_guard<std::mutex>::{ctor}(std::mutex &) Line 458
at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\mutex(458)
MyCoolPlugin.vst3!juce::WaitableEvent::signal() Line 59
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_core\threads\juce_WaitableEvent.cpp(59)
MyCoolPlugin.vst3!juce::Thread::startThreadInternal(juce::Thread::Priority threadPriority) Line 139
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_core\threads\juce_Thread.cpp(139)
MyCoolPlugin.vst3!juce::Thread::startThread(juce::Thread::Priority threadPriority) Line 157
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_core\threads\juce_Thread.cpp(157)
[Inline Frame] MyCoolPlugin.vst3!juce::Timer::TimerThread::addTimer(juce::Timer *) Line 129
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_events\timers\juce_Timer.cpp(129)
MyCoolPlugin.vst3!juce::Timer::startTimer(int interval) Line 306
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_events\timers\juce_Timer.cpp(306)
MyCoolPlugin.vst3!juce::AudioProcessorValueTreeState::AudioProcessorValueTreeState(juce::AudioProcessor & p, juce::UndoManager * um) Line 266
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_processors\utilities\juce_AudioProcessorValueTreeState.cpp(266)
MyCoolPlugin.vst3!juce::AudioProcessorValueTreeState::AudioProcessorValueTreeState(juce::AudioProcessor & processorToConnectTo, juce::UndoManager * undoManagerToUse, const juce::Identifier & valueTreeType, juce::AudioProcessorValueTreeState::ParameterLayout parameterLayout) Line 209
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_processors\utilities\juce_AudioProcessorValueTreeState.cpp(209)
MyCoolPlugin.vst3!DCSnaresAudioProcessor::DCSnaresAudioProcessor() Line 18
at C:\Users\Adam\dev\source\my-cool-plugin\Source\PluginProcessor.cpp(18)
MyCoolPlugin.vst3!createPluginFilter() Line 407
at C:\Users\Adam\dev\source\my-cool-plugin\Source\PluginProcessor.cpp(407)
[Inline Frame] MyCoolPlugin.vst3!juce::createPluginFilterOfType(juce::AudioProcessor::WrapperType) Line 35
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_plugin_client\detail\juce_CreatePluginFilter.h(35)
MyCoolPlugin.vst3!juce::JuceVST3Component::JuceVST3Component(Steinberg::Vst::IHostApplication * h) Line 2436
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_plugin_client\juce_audio_plugin_client_VST3.cpp(2436)
[Inline Frame] MyCoolPlugin.vst3!juce::JucePluginFactory::getClassEntries::__l2::<lambda_1>::operator()(Steinberg::Vst::IHostApplication *) Line 4244
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_plugin_client\juce_audio_plugin_client_VST3.cpp(4244)
MyCoolPlugin.vst3!`juce::JucePluginFactory::getClassEntries'::`2'::<lambda_1>::<lambda_invoker_cdecl>(Steinberg::Vst::IHostApplication * h) Line 4245
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_plugin_client\juce_audio_plugin_client_VST3.cpp(4245)
MyCoolPlugin.vst3!juce::JucePluginFactory::createInstance(const char * cid, const char * sourceIid, void * * obj) Line 4130
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_audio_plugin_client\juce_audio_plugin_client_VST3.cpp(4130)
[Frames may be missing, no binary loaded for Ableton Live 12 Suite.exe]
It seems odd because it’s coming from JUCE code with a similar pattern to most APVTS-based plugins. I suspect it might be a red herring and it might be caused by something else.
Is there anything further I can do to debug the issue?
I’m struggling to make sense of how this could occur
As far as I can tell
The processor is created, it hasan AudioProcessorValueTreeState (I assume it’s just a member variable?)
The AudioProcessorValueTreeState constructor calls startTimer (it is a Timer)
startTimer calls addTimer on the TimerThread (it has a SharedResoucePointer to a TimerThread)
addTimer calls startThread (TimerThread is a Thread)
startThread signals a WaitableEvent (it’s a member variable)
The WaitableEvent then tries to lock a std::mutex (it’s a member variable) via a std::scoped_lock
As far as I tell the mutex pointer being passed to mtx_do_lock is nullptr!?
The only potentially suspect thing to me is the SharedResoucePointer but as TimerThread has it as a member it has a std::shared_ptr to the TimerThread internally, so it’s not obvious to me how this could fail.
Based on the other thread I saw you found some address sanitised issues, is this problem still occurring after resolving those issues?
Could you try updating to at least the very last JUCE 7 commit and let me know if you’re still seeing this issues?
Just chatting with the team, one other thought (although unlikely) was if there could be an issue with another plugin running that is using a different version of JUCE. However, this shouldn’t be an issue if you’re using the Projucer or the official CMake integration, unless you’ve got a custom build system or you’re doing anything or overriding any flags that might impact symbol visibility?
I’ve received .dmp files from a Studio One user which show this stack trace:
msvcp140.dll!mtx_do_lock(_Mtx_internal_imp_t * mtx, const xtime * target) Line 100
at D:\a\_work\1\s\src\vctools\crt\github\stl\src\mutex.cpp(100)
[Inline Frame] My Cool Plugin.vst3!std::_Mutex_base::lock() Line 52
at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\mutex(52)
[Inline Frame] My Cool Plugin.vst3!std::unique_lock<std::mutex>::{ctor}(std::mutex &) Line 144
at C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\mutex(144)
My Cool Plugin.vst3!juce::WaitableEvent::wait(double timeOutMilliseconds) Line 33
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_core\threads\juce_WaitableEvent.cpp(33)
My Cool Plugin.vst3!juce::Thread::threadEntryPoint() Line 89
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_core\threads\juce_Thread.cpp(89)
My Cool Plugin.vst3!juce::threadEntryProc(void * userData) Line 63
at C:\Users\Adam\dev\source\my-cool-plugin\Cache\juce\092995e26ed44e4ec63040a0791aed310c6139aa\modules\juce_core\native\juce_Threads_windows.cpp(63)
[External Code]
No sign of APVTS here but I wonder if it’s just a shorter stack trace for some reason? The plugin has one custom thread (owned and started in the editor), I’m wondering if that might have something to do with this crash.
Yeah it looks like the same basic thing happening, seems to be the wait rather than the signal this time but it looks like the same WaitableEvent (startSuspensionEvent) however, this is part of every JUCE thread and I don’t think there has been any recent changes around this area either .
It feels like the kind of issue ASAN might pick up but of course if you can’t reproduce it I’m not sure what to suggest.
Have you got any sense on the rarity at which this is occurring? how many customers are seeing this?
I think it’s fairly rare but we’ve had around 10-15 reports so far. It’s hard to say how many out of the total Windows users, because it’s the ones that have an issue that complain! But none of our beta testers picked it up. Luckily one of the design team can reproduce it on his home PC so that has helped.
Are they able to reproduce it with a blank session with only one instance of your plugin in the session? any particular steps that they take? I assume this happens on plugin insertion? What version of Windows are they running?
Just a thought are you statically or dynamically linking to the C++ runtime? if it’s dynamic what version of the runtime library have they got installed? and does a statically linked version make any difference?
@anthony-nicholls After switching to statically linking the runtime, the crash goes away. I was not including the redistributable DLLs in my installer. I’ll stick with static linking for now for simplicity…
I’ve always stuck to static linking to avoid this kind of thing too, even if you install the redistributable DLLs there is no guarantee they will always be around or won’t be changed at some point.
Note: Programs that aren’t following the documented restrictions on binary compatibility may encounter null dereferences in mutex machinery. You must follow this rule:
When you mix binaries built by different supported versions of the toolset, the Redistributable version must be at least as new as the latest toolset used by any app component.
You can define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR as an escape hatch.
Looking around online I’m fairly confident this is the issue you’re seeing.
As I think we’ve already concluded, but for the sake of future readers, I think there are really only two solutions
Statically link to the C++ runtime libraries (This is my personal preference but I understand there are good reasons to avoid this)
As part of the installation process, install the redistributable that at least matches the version of the toolset used (I suspect the DAWs in this case were installing older versions)
Looks like there is a possible 3rd solution which is to define _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR, but I’m not sure if all binaries would need to define that (for example the DAW), and it would mean std::mutex couldn’t be used in anything marked constexpr, therefore I think this option should probably be avoided.
Thank you very much!!! I came across this thread purely by accident (well, google:-) and I was having the random crashes on random machines with a completely different program, but exactly the same symptoms: works for some people, crashes for others.