添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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?

The only line in our code is in the AudioProcessor constructor where it’s constructing the APVTS:

MyCoolAudioProcessor:: MyCoolAudioProcessor()
    : AudioProcessor (BusesProperties()
#if ! JucePlugin_IsMidiEffect
#if ! JucePlugin_IsSynth
                          .withInput ("Input", juce::AudioChannelSet::stereo(), true)
#endif
                          .withOutput ("Output", juce::AudioChannelSet::stereo(), true)
#endif
      apvts (*this, nullptr, "Parameters", Parameters::createParameterLayout()) // <--- crashes here

Also to note: This plugin now passes pluginval with strictness 10.

As far as I can tell

  • The processor is created, it has an 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?

    github.com/juce-framework/JUCE

    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?

    It’s a pretty standard setup with JUCE via CMake.

    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.

    adamwilson:

    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 :thinking:.

    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.

    adamwilson:

    Luckily one of the design team can reproduce it on his home PC so that has helped.

    Great news!

    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?

    Yes I believe the tests are with a new blank session, on Windows 11. The other user reports seem to be a mix of Windows 10 and 11 but mostly 11.

    We are currently dynamically linking to the C++ runtime.

    I’ll try statically linking.

    Thanks for the support!

    @adamwilson looking at this a little more I found the following in the Microsoft STL release notes for VS 2022 17.10

  • Fixed mutex’s constructor to be constexpr. #3824 #4000 #4339
  • 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.
  • Note is says

    Programs that aren’t following the documented restrictions on binary compatibility may encounter null dereferences in mutex machinery

    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.

    @anthony-nicholls it appears you have found the root of the issue.

    Now I only have to solve the problem of how to get the maintainers of 4 open source packages that I use to update their code…