Major window handling issues with Logic/ARM

When running my plugins natively in Logic (V10.7.5) on ARM processors, there are several situations where I get the message:

An Audio Unit plug-in reported a problem which might cause the system to become unstable.

I had already mentioned this issue as a reply to another thread, but there had been no reactions (maybe because that topic was already marked as resolved)

I am still not sure, if this is a JUCE or a Logic issue, so let me sum up what I have found out so far.

I created a simple test plugin using the latest JUCE version (7.0.2) from the master branch.

The plugin just has a button that will open an AlertWindow using showOkCancelBox(). I did it like this to have a simple example that can be quickly reproduced, but the issue seems to be the same with any components that are added to the desktop.

I always get that instability message when I do the following:

  • Click the button to open the AlertWindow

  • Click into a different window (e.g. a Finder window)

  • Click into the plugin or the AlertWindow again

In the Console, I could find this error message, but I have no idea what it tries to tell me:

CLIENT ERROR: RemoteAUv2ViewController does not override -<private> and thus cannot react to catastrophic errors beyond logging them

Attaching a debugger to AUHostingServiceXPC_arrow, I could see that there is an endless loop, trying to get the keyboard focus. This is what it looks like in XCode:

Thread 1 Queue : com.apple.main-thread (serial)

#0 0x000000018cce814c in CFStringFindWithOptionsAndLocale ()

#1 0x000000018cd235d4 in -[__NSCFString hasPrefix:] ()

#2 0x00000001948bb7a8 in -[NSViewServiceApplication _shouldFakeMainWindow] ()

#3 0x00000001948bb980 in -[NSViewServiceApplication mainWindow] ()

#4 0x00000001900af348 in -[NSWindow _changeKeyAndMainLimitedOK:] ()

#5 0x000000010b8044e0 in juce::NSViewComponentPeer::grabFocus() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1572

#6 0x000000010b738040 in juce::NSViewComponentPeer::becomeKeyWindow() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1187

#7 0x000000010b7fada0 in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::operator()(objc_object*, objc_selector*) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2357

#8 0x000000010b7faeac in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::__invoke(objc_object*, objc_selector*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2347

#9 0x00000001900af568 in -[NSWindow _changeKeyAndMainLimitedOK:] ()

#10 0x000000010b8044e0 in juce::NSViewComponentPeer::grabFocus() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1572

#11 0x000000010b738040 in juce::NSViewComponentPeer::becomeKeyWindow() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1187

#12 0x000000010b7fada0 in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::operator()(objc_object*, objc_selector*) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2357

#13 0x000000010b7faeac in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::__invoke(objc_object*, objc_selector*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2347

#14 0x00000001900af568 in -[NSWindow _changeKeyAndMainLimitedOK:] ()

#15 0x000000010b8044e0 in juce::NSViewComponentPeer::grabFocus() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1572

#16 0x000000010b738040 in juce::NSViewComponentPeer::becomeKeyWindow() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1187

#17 0x000000010b7fada0 in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::operator()(objc_object*, objc_selector*) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2357

#18 0x000000010b7faeac in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::__invoke(objc_object*, objc_selector*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2347

#19 0x00000001900af568 in -[NSWindow _changeKeyAndMainLimitedOK:] ()

...

#87030 0x000000010b8044e0 in juce::NSViewComponentPeer::grabFocus() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1572

#87031 0x000000010b738040 in juce::NSViewComponentPeer::becomeKeyWindow() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1187

#87032 0x000000010b7fada0 in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::operator()(objc_object*, objc_selector*) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2357

#87033 0x000000010b7faeac in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::__invoke(objc_object*, objc_selector*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2347

#87034 0x00000001900af568 in -[NSWindow _changeKeyAndMainLimitedOK:] ()

#87035 0x000000010b8044e0 in juce::NSViewComponentPeer::grabFocus() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1572

#87036 0x000000010b738040 in juce::NSViewComponentPeer::becomeKeyWindow() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1187

#87037 0x000000010b7fada0 in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::operator()(objc_object*, objc_selector*) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2357

#87038 0x000000010b7faeac in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::__invoke(objc_object*, objc_selector*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2347

#87039 0x00000001900af568 in -[NSWindow _changeKeyAndMainLimitedOK:] ()

#87040 0x000000010b8044e0 in juce::NSViewComponentPeer::grabFocus() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1572

#87041 0x000000010b738040 in juce::NSViewComponentPeer::becomeKeyWindow() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:1187

#87042 0x000000010b7fada0 in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::operator()(objc_object*, objc_selector*) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2357

#87043 0x000000010b7faeac in juce::JuceNSWindowClass::JuceNSWindowClass()::'lambda1'(objc_object*, objc_selector*)::__invoke(objc_object*, objc_selector*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2347

#87044 0x0000000190797580 in _NSShowNonActivatingKeyWindow ()

#87045 0x0000000190157954 in -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] ()

#87046 0x00000001900e18f0 in -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] ()

#87047 0x00000001900e0f5c in -[NSWindow(NSEventRouting) sendEvent:] ()

#87048 0x00000001948ddfb8 in -[NSViewServiceMarshal whileFilteringResponderChain:] ()

#87049 0x00000001948d7194 in -[NSViewServiceMarshal wrap:sendEvent:] ()

#87050 0x00000001948d7354 in -[NSViewServiceMarshal sendEvent:to:] ()

#87051 0x00000001948c2d04 in -[NSWindow(ViewBridgeSwizzle) swizzledSendEvent:] ()

#87052 0x00000001900e0094 in -[NSApplication(NSEvent) sendEvent:] ()

#87053 0x00000001948aac2c in __65-[NSViewServiceApplication sendEventWithoutCatch:withForwarding:]_block_invoke ()

#87054 0x00000001948aab84 in -[NSViewServiceApplication eventHasNotHitWindow:actions:] ()

#87055 0x00000001948aa90c in -[NSViewServiceApplication sendEventWithoutCatch:withForwarding:] ()

#87056 0x00000001948aa6f4 in -[NSViewServiceApplication sendEvent:withForwarding:] ()

#87057 0x000000010b50bb54 in juce::MessageManager::runDispatchLoopUntil(int) at /Volumes/HOFA/Development/JuceLive/modules/juce_events/native/juce_mac_MessageManager.mm:414

#87058 0x000000010b65b888 in juce::ModalComponentManager::runEventLoopForCurrentComponent() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp:281

#87059 0x000000010b65b544 in juce::Component::runModalLoop() at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/components/juce_Component.cpp:1759

#87060 0x000000010b2c4c68 in NewProjectAudioProcessorEditor::buttonClicked(juce::Button*) at /Volumes/HOFA/Development/TestPlugin/NewProject/Source/PluginEditor.cpp:62

#87061 0x000000010b833c24 in juce::Button::sendClickMessage(juce::ModifierKeys const&)::$_34::operator()(juce::Button::Listener&) const at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/buttons/juce_Button.cpp:419

#87062 0x000000010b674314 in void juce::ListenerList<juce::Button::Listener, juce::Array<juce::Button::Listener*, juce::DummyCriticalSection, 0> >::callChecked<juce::Button::sendClickMessage(juce::ModifierKeys const&)::$_34, juce::Component::BailOutChecker>(juce::Component::BailOutChecker const&, juce::Button::sendClickMessage(juce::ModifierKeys const&)::$_34&&) at /Volumes/HOFA/Development/JuceLive/modules/juce_core/containers/juce_ListenerList.h:170

#87063 0x000000010b6736a0 in juce::Button::sendClickMessage(juce::ModifierKeys const&) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/buttons/juce_Button.cpp:419

#87064 0x000000010b673e10 in juce::Button::internalClickCallback(juce::ModifierKeys const&) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/buttons/juce_Button.cpp:368

#87065 0x000000010b6746c8 in juce::Button::mouseUp(juce::MouseEvent const&) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/buttons/juce_Button.cpp:490

#87066 0x000000010b660b28 in juce::Component::internalMouseUp(juce::MouseInputSource, juce::PointerState const&, juce::Time, juce::ModifierKeys) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/components/juce_Component.cpp:2575

#87067 0x000000010b744bf8 in juce::MouseInputSourceInternal::sendMouseUp(juce::Component&, juce::PointerState const&, juce::Time, juce::ModifierKeys) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:140

#87068 0x000000010b74331c in juce::MouseInputSourceInternal::setButtons(juce::PointerState const&, juce::Time, juce::ModifierKeys) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:185

#87069 0x000000010b6664cc in juce::MouseInputSourceInternal::handleEvent(juce::ComponentPeer&, juce::Point<float>, juce::Time, juce::ModifierKeys, float, float, juce::PenDetails) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:312

#87070 0x000000010b666308 in juce::MouseInputSource::handleEvent(juce::ComponentPeer&, juce::Point<float>, long long, juce::ModifierKeys, float, float, juce::PenDetails const&) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp:609

#87071 0x000000010b720e70 in juce::ComponentPeer::handleMouseEvent(juce::MouseInputSource::InputSourceType, juce::Point<float>, juce::ModifierKeys, float, float, long long, juce::PenDetails, int) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/windows/juce_ComponentPeer.cpp:90

#87072 0x000000010b7f1ed8 in juce::NSViewComponentPeer::sendMouseEvent(NSEvent*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:792

#87073 0x000000010b7f2d54 in juce::NSViewComponentPeer::redirectMouseUp(NSEvent*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:674

#87074 0x000000010b7f16ac in void juce::JuceNSViewClass::callOnOwner<void (juce::NSViewComponentPeer::*)(NSEvent*), NSEvent*&>(objc_object*, void (juce::NSViewComponentPeer::*&&)(NSEvent*), NSEvent*&) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2267

#87075 0x000000010b7e55b4 in juce::JuceNSViewClass::asyncMouseUp(objc_object*, objc_selector*, NSEvent*) at /Volumes/HOFA/Development/JuceLive/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm:2272

#87076 0x000000018dc80b30 in __NSThreadPerformPerform ()

#87077 0x000000018cd5da34 in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()

#87078 0x000000018cd5d9c8 in __CFRunLoopDoSource0 ()

#87079 0x000000018cd5d738 in __CFRunLoopDoSources0 ()

#87080 0x000000018cd5c33c in __CFRunLoopRun ()

#87081 0x000000018cd5b8a4 in CFRunLoopRunSpecific ()

#87082 0x00000001963cf3bc in RunCurrentEventLoopInMode ()

#87083 0x00000001963cf04c in ReceiveNextEventCommon ()

#87084 0x00000001963cef48 in _BlockUntilNextEventMatchingListInModeWithFilter ()

#87085 0x000000018ffb4630 in _DPSNextEvent ()

#87086 0x000000018ffb37c0 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()

#87087 0x00000001948bc72c in __77-[NSViewServiceApplication vbNextEventMatchingMask:untilDate:inMode:dequeue:]_block_invoke ()

#87088 0x00000001948bc48c in -[NSViewServiceApplication _withToxicEventMonitorPerform:] ()

#87089 0x00000001948bc68c in -[NSViewServiceApplication vbNextEventMatchingMask:untilDate:inMode:dequeue:] ()

#87090 0x00000001948aa188 in -[NSViewServiceApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()

#87091 0x000000018ffa7bf0 in -[NSApplication run] ()

#87092 0x000000018ff7f058 in NSApplicationMain ()

#87093 0x000000018c9f6734 in _xpc_objc_main ()

#87094 0x000000018c9f5fe0 in xpc_main ()

#87095 0x00000001948a5170 in -[NSXPCSharedListener resume] ()

#87096 0x00000001948becf0 in NSViewServiceMain ()

#87097 0x000000010235e3d8 in ___lldb_unnamed_symbol93 ()

#87098 0x000000018c953e50 in start ()

Trying to debug this issue using breakpoints is quite impossible, as this is problem of keyboard focus and the keyboard focus is always lost when a breakpoint is triggered.

So I have added a FileLogger to NSViewComponentPeer. It outputs the names of the functions that are called (and their return values where necessary).

The output when running Logic using Rosetta (where the problem does not occur) looks like this:

canBecomeKeyWindow → true
canBecomeKeyWindow → true
isBlockedByModalComponent → false
becomeKey
canBecomeKeyWindow → true
becomeKeyWindow
grabFocus
viewFocusGain
canBecomeKeyWindow → true
isBlockedByModalComponent → false
redirectMouseDown
toFront
canBecomeMainWindow → false
redirectMouseUp

The output of the native version is:

canBecomeKeyWindow → true
canBecomeKeyWindow → true
becomeKeyWindow
grabFocus
canBecomeMainWindow → false
canBecomeKeyWindow → true
isBlockedByModalComponent → false
canBecomeKeyWindow → true
becomeKeyWindow
grabFocus
canBecomeMainWindow → false
canBecomeKeyWindow → true
isBlockedByModalComponent → false
canBecomeKeyWindow → true
becomeKeyWindow
grabFocus
canBecomeMainWindow → false
canBecomeKeyWindow → true
isBlockedByModalComponent → false
canBecomeKeyWindow → true
becomeKeyWindow
grabFocus
… This is repeated some thousand times …

So in the beginning the calls to isBlockedByModalComponent() and becomeKey() are missing here. Instead, canBecomeMainWindow() is called. To me this sounds like Logic tries to make this AlertWindow the main window which is not possible (and makes no sense).

Does anybody have an idea, what is happening here and what could be done to avoid it.

Thanks for any hints!

1 Like

one solution is to not use modal dialog

That’s a workaround, but not a solution :wink:

We are having the exact same issue. Our plugin has 2 windows, one main and another child window. We have JUCE_MODAL_LOOPS_PERMITTED == 1
We saw thee previous post by @gphofa
We are getting random crashes in Logic native on ARM.

Any help would be appreciated.

Would this be solved if we build an AUv3?
Anyone knows how to build an AUv3 on CMAKE?

Bump!

I am very troubled by the same problem.

Please don’t view this response as an attempt to not acknowledge the problem, but I would really strongly recommend not using any modal loops whatsoever. They are a constant source of problems, some of which may be impossible to resolve. It is worth investing the development time to remove any modal loops you are using.

1 Like

To add to Tom’s reply: Jules wrote about modal loops and why you should avoid them too many times to count.

2 Likes

This issue is not a problem of modal loops. It occurs with any Component that is put onto the Desktop, no matter if it is running in a modal loop or not.

1 Like

Hi, would be great if we could get some attention on this if possible, I’ve a number of plugins that are out in the wild that did work natively on silicon, but no longer do. thx

I’m hitting the same problem right now.

I confirm it happens in relation with a window beind displayed by the plug-in.
This is happening in a plug-in with a long history and it’s not currently feasible to refactor it to completely avoid modal loops.

Other workarounds (aside from using Rosetta, which I confirm it works) ?

EDIT: I’ve just skimmed through this topic and only after posting I’ve read it’s more likely an issue about components on the desktop. Is that confirmed that modal loops are not the culprit?

Something i found out, a secondary window should never created instantly after plug-in creation, there should always be a delay. I usually use a timer for that.

But modal loops I would avoid at all cost. With todays lambda options and safe-pointers it shouldn’t be to complicated to modernize the code.

I have found a way to consistently reproduce the problem.

It happens also with async windows, i.e. no runModalLoop() involved.

The triggering factor, is if the window is displayed while Logic is not the focused program.

To demonstrate that, I have created a default plug-in that in its editor launches an async AlertWindow after a 5 seconds delay.

    auto action = []
    {
        juce::AlertWindow::showMessageBoxAsync (juce::AlertWindow::NoIcon, "async message box", "click me");
    };
    
    juce::Timer::callAfterDelay (5000, action);

If I instantiate the plug-in, then simply wait for the window to appear, I can click on it without problems.

If I instantiate the plug-in, then immediately bring another window (e.g. Finder) in the foreground while the 5 seconds pass, then clicking on the AlertWindow that appears in the background triggers the problem.

Video here:

recording.mov.zip (2.5 MB)

2 Likes

I’ve got a patch on the way that should fix this

4 Likes

Fantastic! Thanks.
Do you know how long it will take to become public?
Just to make an informed decision about an upcoming release currently being held back by this.

nice one! :slight_smile:

I have noticed a fix has been introduced with this commit:

and that fixes the crash, but still there is some undesired behavior (see video, sorry for the bad quality, I had to reduce resolution to stay within 8 MB limit of the forum):

recording 2 480p.mov.zip (2.9 MB)

When the AlertWindow appears in the background of the Finder window, if I try to click its OK button, the AlertWindow goes behind the plug-in window instead of being dismissed, and there seems no way to bring it in front again.

That is a big problem if the AlertWindow is small and entirely within the screen area occupied by the plug-in window (which is often the case), because in that case when the AlertWidow goes behind the plug-in window, it’s completely invisible to the user, but still its presence blocks the interaction with the plug-in window.

Even worse, if at that point the user clicks inside Logic, the AlertWindow goes even behind Logic itself, making it ureachable even further.

One workaround could be to create the AlertWindow as a child of the plug-in Editor, but AFAIK there is no API for that at the moment, and anyway that could work only in those cases where the AlertWindow is guaranteed to be smaller than the plug-in.
Another workaround could be to instruct the AlertWindow to stay always on top, AFAIK there is no API for that at the moment either, and also then it could become a fighting game between all always-on-top windows, if the plug-in window is also created as such by the DAW.

This seems like a corner case, but it is not, because that’s the typical situation when a plug-in allows a file to be dragged on its editor: the user brings the Finder in front of everything, then drags and drops the file on the plug-in and that’s when any AlertWindow displayed by the plug-in in response will suffer from this problem

Glad to hear that this commit fixes the crash:

Unfortunately the window-ordering issues in out-of-process-hosted plugins on macOS are proving more difficult to track down. They’re still on my backlog.

1 Like

Crash fixed! Thx so much guys.

Do you have a rough estimate for when this will have a possibility to be looked at?
Any answer is welcome, in order to make an informed decision for an upcoming release, thanks.

I had a quick look today and still didn’t really get anywhere. It seems that the official Apple guidance is “don’t open secondary windows in AU plugins”. If they’re not really testing or supporting this use-case, then unfortunately I don’t think that we can.

2 Likes