od1
February 7, 2023, 3:40pm
1
Hello JUCEers.
I am having a lot of problems with VST2 when updating to JUCE 7 and using pluginval. Maybe this is the wrong forum for this, please forgive me if that is the case.
When running pluginval after a few opening and closings I get an exception, which I don’t get for the VST3 tests. I’ve searched on the forums and can’t find any helpful information regarding this.
Tried emptying the PluginEditor of everything but setting the size and fill with a background colour in paint but it still happens.
Any ideas?
|>|pluginval.exe!juce::WeakReference<juce::Component,juce::ReferenceCountedObject>::SharedPointer::get() Line 129|C++|
|---|---|---|
| |pluginval.exe!juce::WeakReference<juce::Component,juce::ReferenceCountedObject>::Master::getSharedPointer(juce::Component * object) Line 170|C++|
| |pluginval.exe!juce::WeakReference<juce::Component,juce::ReferenceCountedObject>::getRef(juce::Component * o) Line 204|C++|
| |pluginval.exe!juce::WeakReference<juce::Component,juce::ReferenceCountedObject>::WeakReference<juce::Component,juce::ReferenceCountedObject>(juce::Component * object) Line 84|C++|
| |pluginval.exe!juce::Component::SafePointer<juce::VSTPluginWindow>::SafePointer<juce::VSTPluginWindow>(juce::VSTPluginWindow * component) Line 2293|C++|
| |pluginval.exe!juce::VSTPluginWindow::vstHookWndProc(HWND__ * hW, unsigned int message, unsigned __int64 wParam, __int64 lParam) Line 3305|C++|
| |[External Code]||
| |MyPlugin.dll!juce::HWNDComponentPeer::destroyWindowCallback(void * handle) Line 2701|C++|
| |MyPlugin.dll!juce::HWNDComponentPeer::callFunctionIfNotLocked(void *(*)(void *) callback, void * userData) Line 3952|C++|
| |MyPlugin.dll!juce::HWNDComponentPeer::~HWNDComponentPeer() Line 1753|C++|
| |[External Code]||
| |MyPlugin.dll!juce::Component::removeFromDesktop() Line 772|C++|
| |MyPlugin.dll!juce::Component::~Component() Line 529|C++|
| |MyPlugin.dll!JuceVSTWrapper::EditorCompWrapper::~EditorCompWrapper() Line 989|C++|
| |[External Code]||
| |MyPlugin.dll!JuceVSTWrapper::deleteEditor(bool canDeleteLaterIfModal) Line 882|C++|
| |MyPlugin.dll!JuceVSTWrapper::handleCloseEditor(JuceVSTWrapper::VstOpCodeArguments __formal) Line 1657|C++|
| |MyPlugin.dll!JuceVSTWrapper::dispatcher(int opCode, JuceVSTWrapper::VstOpCodeArguments args) Line 908|C++|
| |MyPlugin.dll!JuceVSTWrapper::dispatcherCB(Vst2::AEffect * vstInterface, int opCode, int index, __int64 value, void * ptr, float opt) Line 955|C++|
| |pluginval.exe!juce::VSTPluginInstance::dispatch(int opcode, int index, __int64 value, void * const ptr, float opt) Line 1744|C++|
| |pluginval.exe!juce::VSTPluginWindow::dispatch(const int opcode, const int index, const int value, void * const ptr, float opt) Line 3265|C++|
| |pluginval.exe!juce::VSTPluginWindow::closePluginWindow() Line 3244|C++|
| |pluginval.exe!juce::VSTPluginWindow::~VSTPluginWindow() Line 2814|C++|
| |[External Code]||
| |pluginval.exe!deleteEditorOnMessageThread::__l2::<lambda>() Line 188|C++|
| |[External Code]||
| |pluginval.exe!`juce::MessageManager::callAsync'::`2'::AsyncCallInvoker::messageCallback() Line 197|C++|
| |pluginval.exe!juce::InternalMessageQueue::dispatchMessage(juce::MessageManager::MessageBase * message) Line 202|C++|
| |pluginval.exe!juce::InternalMessageQueue::dispatchMessages() Line 240|C++|
| |pluginval.exe!juce::InternalMessageQueue::dispatchNextMessage(bool returnIfNoPendingMessages) Line 125|C++|
| |pluginval.exe!juce::dispatchNextMessageOnSystemQueue(bool returnIfNoPendingMessages) Line 266|C++|
| |pluginval.exe!juce::MessageManager::runDispatchLoop() Line 109|C++|
| |pluginval.exe!juce::JUCEApplicationBase::main() Line 269|C++|
| |pluginval.exe!WinMain(HINSTANCE__ * __formal, HINSTANCE__ * __formal, char * __formal, int __formal) Line 173|C++|
| |[External Code]||
reuk
February 7, 2023, 6:49pm
2
Have you tested any of the JUCE example plugins to see whether those also have the same problem? If they do, then the problem is likely to be in the JUCE wrapper or hosting code.
od1
February 8, 2023, 1:21pm
3
Sorry for a slow reply, I’ve been investigating thoroughly.
It also happens using the AudioPluginDemo.dll
, and to trigger it on that plugin I have to click on my code editor so that the plugin is not on top when running pluginval.
In juce_VSTPluginFormat.cpp
, When I changed
void broughtToFront() override
{
activeVSTWindows.removeFirstMatchingValue (this);
activeVSTWindows.add (this);
#if JUCE_MAC
dispatch (Vst2::effEditTop, 0, 0, nullptr, 0);
#endif
}
to
void broughtToFront() override
{
// activeVSTWindows.removeFirstMatchingValue (this);
// activeVSTWindows.add (this);
#if JUCE_MAC
dispatch (Vst2::effEditTop, 0, 0, nullptr, 0);
#endif
}
It passes (change is only for pluginval). Seems to be to be some kind of race on the contents of activeVSTWindows
which is just a static variable.
1 Like
reuk
February 8, 2023, 3:32pm
4
Thanks for the additional details. I’ve reproduced and debugged the problem, and we should have a fix out in a few days. Pluginval will also need to be updated once the fix has been merged.
2 Likes
od1
February 8, 2023, 3:55pm
5
ping @dave96 you might be interested in this as well.
Is this something that could affect other hosts, or is it just going to be isolated to pluginval?
reuk
February 8, 2023, 7:21pm
7
It looks like it might affect other VST2 hosts too.
That’s interesting, something due to a recent change or do we expect to affect things going back a long time?
reuk
February 8, 2023, 7:59pm
9
Difficult to say; the fix changes lines in the VSTPluginWindow that were last touched ten years ago. The particular behaviour we’re seeing, where broughtToFront
is called while the editor destructor is running, might have been in place all along, or it might have been introduced recently.
1 Like
abrykt
February 16, 2023, 12:27pm
10
I saw this commit pushed to develop:
committed 10:29PM - 14 Feb 23 UTC
On Windows, broughtToFront may be called during the destructor of
VSTPluginHost,… adding the window back into activeVSTWindows, leading to
a heap-use-after-free in vstHookWndProc.
This change means that broughtToFront will only reorder
activeVSTWindows; it will never add a window that's not already in the
list.
Does this mean this is fixed?
If so, could you outline what changes are needed on the host side?
Thanks!
abrykt
February 16, 2023, 12:30pm
11
…Is maybe an update of pluginval
to point to this commit in juce sufficient?
reuk
February 16, 2023, 12:47pm
12
You’re right, the issue should be fixed by this commit:
committed 10:29PM - 14 Feb 23 UTC
On Windows, broughtToFront may be called during the destructor of
VSTPluginHost,… adding the window back into activeVSTWindows, leading to
a heap-use-after-free in vstHookWndProc.
This change means that broughtToFront will only reorder
activeVSTWindows; it will never add a window that's not already in the
list.
Just updating the version of JUCE used in pluginval should be sufficient to avoid the issue.
dave96
February 16, 2023, 3:19pm
14
If someone wants to do that on a fork then open a PR it would happen much quicker
That way I can check it all still builds on the CI.
sudara
February 20, 2023, 3:31pm
15
I opened a PR, but am running into another issue with the JUCE VST3 demos segfaulting on all platforms after updating pluginval to latest develop .
@reuk I couldn’t reproduce locally on my own plugins, but after building the JUCE demos and running them through pluginval, I saw EXC_BAD_ACCESS in getVst3SpeakerArrangement
, specifically on BigInteger::isNegative()
inside the std::find_if
— maybe related to this recent commit ?
On the pluginval side, it’s coming from the supportedLayoutsWithNamedChannels
call inside listBuses(false)
: pluginval/BusTests.cpp at 8756d8426529305f1efa5c653fb4688b2edd3d2a · Tracktion/pluginval · GitHub — happy to make any changes there if you see something that’s off!
reuk
February 23, 2023, 7:03pm
16
I can repro this now, investigating…
1 Like
reuk
February 23, 2023, 7:41pm
17
Looks like a typo here:
}
const auto getPotentialArrangements = [&] (bool isInput) -> std::optional<std::vector<Vst::SpeakerArrangement>>
{
std::vector<Vst::SpeakerArrangement> result;
for (int i = 0; i < layouts.getBuses (isInput).size(); ++i)
{
const auto& requested = layouts.getChannelSet (isInput, i);
if (const auto arr = getVst3SpeakerArrangement (requested.isDisabled() ? getBus (true, i)->getLastEnabledLayout() : requested))
result.push_back (*arr);
else
return {};
}
return result;
};
auto inArrangements = getPotentialArrangements (true);
auto outArrangements = getPotentialArrangements (false);
I think that should be getBus (isInput, i)
rather than getBus (true, i)
.
Thanks for reporting! Pluginval catching real bugs once again…
2 Likes
sudara
February 23, 2023, 8:31pm
18
Great work! I feel bad, I just lopped this into your lap instead of digging into the actual logic and helping out more. Thanks for looking into it!
reuk
March 2, 2023, 7:43pm
19
The fix is finally public:
committed 12:03PM - 02 Mar 23 UTC
sudara:
I feel bad
No worries, I shouldn’t be committing bugs in the first place!
1 Like
sudara
March 2, 2023, 10:59pm
20
Awesome, this makes pluginval green again, thanx!
very high bar of you, let me know if you find the secret!