JUCE makes double editor creation, Why?

I have found weird behavior in JUCE VST plugin which tries to create an editor two times (creates/removes/creates) and deletes all child components. I mean it should remove MainWindow and all child components will be destroyed due to std::unique_ptr but instead JUCE trying to destroy all child in deleteEditor->editorBeingDeleted->deleteAllChildren:

Ok, Let’s go forward with simple steps:

  1. juce_VST_Wrapper.cpp, handleGetEditorBounds - first one editor created here
  2. juce_VST_Wrapper.cpp, handleOpenEditor - second one here, and before create a new one it removing deleteEditor(true)

Is it a known issue? Do you have any workarounds?

Many thanks

In what way(s) is this problematic? What is it that you’re doing that’s not aligning with this/allowing this to work?

Some hosts may be open and close (create/delete) the editor multiple times in succession. That is just a thing you will have to be prepared for. Don’t do anything too expensive in the editor constructor.

Child UI components of MainWindow using juce::ChangeListener for event subscription and when MainWindow deletes earlier than the component itself I have a dangling pointer.

deleteAllChildren code removes child components without respect to parent (MainWindow) class. So, Instead of removing all childrens first and then remove MainWindow it removes all components in some free order.

Remove your change listeners in your destructors?

Yeep :slight_smile: and interface to change listener getting from MainWindow

Ok, I have moved ChangeBroadcaster out from the MainWindow into the AudioProcessor class and now it works normally and GUI components could normally add a listener in the constructor and remove it in the destructor. But in my opinion right place for ChangeBroadcaster should be in MainWindow because of user actions.

that sounds like the wrong design decision, making your AudioProcessor a change broadcaster.

Your editor should poll the atomic values that live in your processor with a Timer.
ChangeBroadcaster uses AsyncUpdater internally to broadcast the message.

on OS X, the message queue uses this internally:

ReferenceCountedArray<MessageManager::MessageBase, CriticalSection> messages;

The CriticalSection is the problem here, because it involves system calls when it locks.

    void post (MessageManager::MessageBase* const message)
    {
        messages.add (message);
        wakeUp();
    }

add() is:

    ObjectClass* add (ObjectClass* newObject)
    {
        const ScopedLockType lock (getLock());
        values.add (newObject);

        if (newObject != nullptr)
            newObject->incReferenceCount();

        return newObject;
    }

so, there ya go. Calling triggerAsyncUpdate() from the audio thread locks and makes system calls.
and that is what happens when you call sendChangeMessage() from the audio thread:

void ChangeBroadcaster::sendChangeMessage()
{
    if (anyListeners)
        broadcastCallback.triggerAsyncUpdate();
}

I’m not blocking the main audio thread, instead, I have another thread that listens to DSP changes and if occurs asks ChangeBroadcaster to send messages for all.
Also, the editor could ask ChangeBroadcaster to signal all others components using atomic events.

You weren’t clear when you said

I assumed this meant:

class MyAudioProcessor : public juce::AudioProcessor, 
                         public juce::ChangeBroadcaster 
{