Hosted VST3: threading issue

In VST3PluginInstance::getStateInformation we have JUCE_ASSERT_MESSAGE_THREAD and then a MessageManagerLock with the comment that “The VST3 plugin format requires that get/set state calls are made from the message thread”. This is only true for real time processing, however. For instance, in Acon Acoustica, when applying an effect via offline rendering, getState is called from a non-main thread. This can (and does) create a deadlock when writing a plugin that can load other (VST3) plugins, so I think this lock and assertion have to go (there is a similar issue with prepareToPlay which Acon Acoustica also calls from a non-UI thread, but in that case, the VST3 guidelines clearly require that plugin initialization has to occur on the main thread, so that is an error by the developers there).

Any thoughts?

Can you provide a link to the VST3 docs/specs that indicates it’s valid to call getState from a thread other than the main thread? From the workflow diagrams, it looks to me like it’s only valid to call this on the “UI thread”, and I don’t see any mention of “thread” in the class docs for IComponent.

1 Like

I got that impression from this discussion thread: Is IComponent::getState()/setState() thread-safe? - VST 3 SDK - Steinberg Forums where Yvan from Steinberg made a statement in that direction. Has that changed since 2018?

Edit: also this section in the FAQ ( Processing - VST 3 Developer Portal ) states that state getting/setting can occur on the processing thread in an offline context.

There is a similar issue in the JUCE VST3 plugin format: in prepareToPlay, we have

// The VST3 spec requires that IComponent::setupProcessing() is called on the message
        // thread. If you call it from a different thread, some plugins may break.
        JUCE_ASSERT_MESSAGE_THREAD
        MessageManagerLock lock;

This is all fine in realtime rendering, but in offline rendering some hosts just use one single background thread to first prepare the plugin, then do the rendering. If the real message thread is then waiting for prepareToPlay to return because it wants to show some rendering automation for instance, the whole thing stalls. Happens in Acon Acoustica for example.