Doc clarification on IRunLoop

Many plugins (eg, JUCE) implicitly require that IRunLoop calls its event handlers on the UI (“main” thread, in JUCE terms), but there’s no such requirement listed in the IRunLoop documentation.

The most naive way to implement IRunLoop on Linux is to spawn a thread to call poll() on the file descriptors of interest, and create timerfds for timer handlers. But this causes undefined behavior/memory safety violations in plugins that expect their handlers to be called by the UI thread.

Is it correct to say that IRunLoop implementers must call registered event handlers on the UI thread, or are plugins that assume that handlers are called on the UI thread incorrect?

Another clarification question:

Is a host allowed to invoke the timer/event handlers registered with its IPlugFrame’s IRunLoop interface after IPlugView::remove? Or must the plugin support events that happen after its view has been destroyed?

all controller functions are in the UI Thread: Edit Controller Call Sequence - VST 3 Developer Portal (steinbergmedia.github.io)

IPlugView::remove is called when the UI is closed, but the plugin still alive, so any events should still work.
Provide A Runloop On Linux - VST 3 Developer Portal (steinbergmedia.github.io)

I’m asking about IEventHandler and ITimerHandler, not IEditController. Do IEventHandler::onFDisSet() and ITimerHandler::onTimer need to be called from the UI thread?

The reason for these questions is that JUCE VST3 plugins crash the host process if you don’t guarantee that the handlers are called on the UI thread and that no events are delivered after IPlugView::remove.

As plug-ins most likely need to use the timer stuff inside the edit controller and to make the life of a plug-in developer more convenient, the calls to and from IEventHandler and ITimerHandler must be done on the UI/main thread.
The IPlugView object is not destroyed when you call IPlugView::remove so calling the object afterwards should not crash. There was a bug in earlier versions of Juce, but that was fixed last year or the year before I think.

Thanks! This wasn’t clear from the docs.