Crash on HWNDComponentPeer::destroyWindowCallback

It just feels like you’re overcomplicating things a bit.
You simply need a thread that does your initialisation, when you come to load a plugin, use MessageManager::callAsync to post a message and do the initialisation inside the body of the lambda you pass to it. You’ll need a WaitableEvent to wait in the thread until the message has been dispatched and completed.

In Tracktion Engine we encapsulate this functionality in to callBlocking https://github.com/Tracktion/tracktion_engine/blob/381e3220571419d726be759f305576bba2df46cc/modules/tracktion_engine/utilities/tracktion_AsyncFunctionUtils.h#L205
You need to make sure you don’t wait indefinitely such as if a quit message has been posted.

But the other part of this is you need some kind of “load context” which has an atomic flag which you can check to see if you need to bail out of your loading. Then you can simply set this if the user closes a project whilst its being loaded for example.

1 Like
class PluginPool : private Timer
{
public:
	PluginPool()
	{
		OwnedArray<PluginDescription> descs;

		vst.findAllTypesForFile(descs, "path\\to\\your\\Kontakt.dll");
		pluginDesc = *descs[0];

		startTimer(1);
	}

	~PluginPool()
	{
		stopTimer();
		jassertfalse; // L1
	}

private:
	void timerCallback() override
	{
		AudioPluginInstance *thisPluginInstance = pluginInstances.add(vst.createInstanceFromDescription(pluginDesc, 44100.0, 1024).release());

		if (firstStateInfo.getSize() == 0) thisPluginInstance->getStateInformation(firstStateInfo);
		else
		{
			MessageManager::callAsync([] { JUCEApplicationBase::getInstance()->systemRequestedQuit(); });
			jassertfalse; // L2
			thisPluginInstance->setStateInformation(firstStateInfo.getData(), (int)firstStateInfo.getSize());
			jassertfalse; // L3
		}
	}

	VSTPluginFormat vst;
	PluginDescription pluginDesc;
	MemoryBlock firstStateInfo;
	OwnedArray<AudioPluginInstance> pluginInstances;
};

I know that there will be other (perhaps simpler) ways to solve it, but I am just curious why the breakpoint L1 will be triggered instead of L3 after the breakpoint L2 is triggered here. This makes no sense. @dave96 @ed95 Do any of you know the reason here?

I think you really need to examine the stack trace to determine that. Presumably something is destroying the PluginPool?

Maybe set an actual break point on the L2 line and step through it?

After loading all the symbols from the Microsoft symbol server, I finally found that after calling setStateInformation on Kontakt, Kontakt would call DialogBoxIndirectParamW and then pop up a modal dialog box. In the modal dialog box of Windows, the message loop of the parent window will be blocked, but the dialog box itself will create a new message loop. And this new message loop will also dispatch the message of the parent window (by calling DispatchMessageWorker). So the problem I encountered appeared.