VST3 Crashing Due to IEditController Thread Issues

We’ve had some reports of crashes with the AGain VST3 example plugin and after another developer looked deeply in to the problem and posted this thread on the Steinberg forums (https://sdk.steinberg.net/viewtopic.php?f=4&t=628) it appears it could be a threading issue stemming from the JUCE implementation.

It looks like any editController calls can only be made from the message thread. This seems to be violated in several places in juce_VST3PluginFormat.cpp, mainly when calling setParamNormalized.

Now that Stenberg has deprecated VST2, this is probably higher priority as we can no longer advise our customers to use the VST2 version of plugins.

As much as it pains me to say it, maybe adding a const ScopedLock sl (lock); around the audio thread calls to setParamNormalized might fix it?

1 Like

Looking at the VST3 SDK a little more, it seems like a lock might not do it. The plugin UI could be accessing the values from the message thread so it’s not safe to ever set them from another thread. From the docs:

	/** Sets the normalized value to the parameter associated to the paramID. The controller must never
	    pass this value-change back to the host via the IComponentHandler. It should update the according
		GUI element(s) only!*/
	virtual tresult PLUGIN_API setParamNormalized (ParamID id, ParamValue value) = 0;

Thanks Dave, we’ll look into this.

Hi there. I have just upgraded to and tried the very latest v6 code and it still has a problem with the VST3 plugin Subdivine. (It happens with the free trial which you can get here: https://diginoiz.com/series/subdivine/ ) Simply load this plugin into the JUCE AudioPluginHost project, connect the midi inputs and audio outs and show the interface…play some MIDI notes from your controller and wiggle the “R” slider. This is very easy to repro.

I am not sure if this is a bug in the plugin Subdivine or if this is something that the VST3 plugin host should handle better. The devs behind Subdivine suggest that parameters should not be sent on the audio threads. I have tried locking, as suggested above. That did not help. Thanks for your help. (=

Hey JUCE Team, anyone have any info on this? Your help would be appreciated. (=

It’s still on our todo list.

It’s an important problem, but an initial triage suggests that it is a large amount of work to address properly, so it’s difficult to schedule.

Ok - thank you! I was just double checking that it would be addressed! I appreciate it. (=

Just checking to see if this is in the dev pipe? Thanks for your amazing work.

We have started work on this.


Awesome to hear!!! (=

1 Like

@t0m While working on this, is there any chance you could expose the full VST3 plugin state? Right now there is no way for hosts to access a plugin’s Vst::IEditController, because ExternalPlugin::getPlatformSpecificData only exposes Vst::IComponent. Among other issues, this makes it impossible to save .vstpreset files, which include state from the Vst::IEditController.

There’s a little more info about this in this thread.

We’ve now pushed some updates to the VST3 host and client code which should correctly implement the threading model specified in Steinberg’s documentation:

I’ve tested this with the tools you might expect (address sanitizer, thread sanitizer, pluginval, JUCE’s demo plugins, and the third-party plugins mentioned earlier in this thread) and it works correctly in the cases I tried. In particular, Steinberg’s hostchecker plugin is much happier with JUCE’s hosting now!

For a low-level change like this which changes the threads used to call certain functions, it’s possible there will be subtle consequences that may affect the behaviour of existing hosts/plugins. If you encounter any issues, or have any other feedback, please let me know.