Bug Report: Hosted AU Plugin Window Crashes in NSViewAttachment#removeFromParent

Hey team,

I’ve recently bumped my JUCE version from 8.0.3 to 8.0.8 and started seeing this crash happen somewhat consistently while interacting with hosted AU interfaces:

Thread 0 Crashed:: MainThread Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib               	       0x19ab99820 objc_msgSend + 32
1   CoreAudioKit                  	       0x1fcd1888c -[CAAppleAUCustomViewBase cleanup] + 60
2   AppKit                        	       0x19efb7410 -[NSView _setSuperview:] + 272
3   AppKit                        	       0x19efd6888 -[NSView removeFromSuperview] + 156
4   dime [ms]                     	       0x318eeb7f8 juce::NSViewAttachment::removeFromParent() + 56 (juce_NSViewComponent_mac.mm:126)
5   dime [ms]                     	       0x318ee9374 juce::NSViewAttachment::componentPeerChanged() + 152 (juce_NSViewComponent_mac.mm:97)
6   dime [ms]                     	       0x318f60dd8 juce::ComponentMovementWatcher::componentParentHierarchyChanged(juce::Component&) + 204 (juce_ComponentMovementWatcher.cpp:68)
7   dime [ms]                     	       0x31918e404 juce::Component::internalHierarchyChanged()::$_0::operator()(juce::ComponentListener&) const + 44 (juce_Component.cpp:1413)
8   dime [ms]                     	       0x31918e304 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0>>::callCheckedExcluding<juce::Component::internalHierarchyChanged()::$_0, juce::Component::BailOutChecker>(juce::ComponentListener*, juce::Component::BailOutChecker const&, juce::Component::internalHierarchyChanged()::$_0&&) + 476 (juce_ListenerList.h:273)
9   dime [ms]                     	       0x318f329a8 void juce::ListenerList<juce::ComponentListener, juce::Array<juce::ComponentListener*, juce::DummyCriticalSection, 0>>::callChecked<juce::Component::internalHierarchyChanged()::$_0, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Component::internalHierarchyChanged()::$_0&&) + 44 (juce_ListenerList.h:217)
10  dime [ms]                     	       0x318f2da98 juce::Component::internalHierarchyChanged() + 128 (juce_Component.cpp:1413)
11  dime [ms]                     	       0x318f2dea8 juce::Component::addToDesktop(int, void*) + 524 (juce_Component.cpp:450)
12  dime [ms]                     	       0x319002bc8 juce::TopLevelWindow::addToDesktop(int, void*) + 156 (juce_TopLevelWindow.cpp:183)
13  dime [ms]                     	       0x318f2e72c juce::Component::setOpaque(bool) + 160 (juce_Component.cpp:581)
14  dime [ms]                     	       0x318f6a5b8 juce::ResizableWindow::setBackgroundColour(juce::Colour) + 140 (juce_ResizableWindow.cpp:395)

As you can see from the trace the issue begins with a call to setBackgroundColour on the DocumentWindow object (subclass of ResizableWindow) which holds a reference to the AU plugin instance, and takes ownership of its editor:

namespace timeoffaudio {
    class PluginWindow final : public juce::DocumentWindow {
    public:
        // ...

        explicit PluginWindow (juce::AudioPluginInstance& pI /* ...*/)
            : DocumentWindow (/*...*/),
              pluginInstance (pI),
              {
            // ...

            if (auto* ui = createProcessorEditor ()) {
                setContentOwned (ui, true);
                setResizable (ui->isResizable(), false);
            }

            setConstrainer (&constrainer);
            setTopLeftPosition (options.xPos, options.yPos);

            // ...

            Component::setVisible (true);
        }

        // ...

    private:
        std::string pluginInstanceKey;
        juce::AudioPluginInstance& pluginInstance;
        timeoffaudio::PluginWindowLookAndFeel pluginWindowLookAndFeel;
        const juce::PluginHostType currentDAW;

        juce::AudioProcessorEditor* createProcessorEditor () {
            if (pluginInstance.hasEditor())
                if (auto* ui = pluginInstance.createEditorIfNeeded()) return ui;

            jassertfalse;
            return {};
        }
        
        // ...
    }
}

I suspect this could be a bug, simply due to the fact I have not seen this in months and now have been hit with this crash many times already since upgrading. However, I could be wrong.

Thanks for taking a look at this!

1 Like

Thanks for reporting this!

Can you replicate this crash using the AudioPluginHost and does this happen with JUCE only plugins or are you seeing crashes with other plugins?