Editor component destroyed before callback finished


#1

Hi,

in some cases it can happen (for example if a plugin-window in cubase is marked as “always on the top”) that the VST-Plugin-Editor will be closed (VstWrapper::deleteEditor()) before a callback like mouseDown() is finished, and that will result in a crash.
Has anyone an idea how to avoid this?


#2

How is the fact that it’s always-on-top relevent? Do you mean you’ve made a juce window that’s always on top, or is that an option in cubase?


#3

I mean the cubase function (it can be activated with right mouse click under the title bar, preset menu) . If the main window focus is changed from cubase to another application, all windows that have the “cubase-always on the top flag” will disappear. This can happen if you use a pop-up menu inside the plugin, and click outside the window, or when another application catches the focus.
The important thing is that it seams that cubase uses a another thread to close the gui (via vst-sdk function), while the message thread is doing a mouse-down callback in the same gui-object. Maybe the VstWrapper should wait until a running callbacks are finished.


#4

Ah, I see. That’s nasty… I guess that some of the juce event handling would need to have more checks about whether the component is still valid before sending the events. Where’s the crash?


#5

In my case, the application stops in a mouseDown Callback, after processing a popup-menu (PopUpMenu.show()) trying to lock a CriticalSection which was deleted before (i suppose while processing the popup-menu message loop) but it would crash in any other case too, when accessing a member.
So, the deletion does not have to be from another thread, but it can.

[code] ntdll.dll!7c92b1fa()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!7c96d414()
ntdll.dll!7c97c5cf()
ntdll.dll!7c9703b0()
ntdll.dll!7c9704a8()
ntdll.dll!7c970484()
ntdll.dll!7c911046()

test_debug.dll!juce::CriticalSection::enter() Line 81 + 0xc bytes C++
test_debug.dll!juce::ScopedLock::ScopedLock(const juce::CriticalSection & lock={…}) Line 75 + 0x33 bytes C++
test_debug.dll!my_Envelope::setXmlString(juce::String s={…}) Line 330 + 0xf bytes C++
test_debug.dll!my_EnvelopeBox::setXmlString(juce::String s={…}) Line 58 + 0x23 bytes C++
test_debug.dll!my_EnvelopeBox::mouseDown(const juce::MouseEvent & e={…}) Line 389 C++
test_debug.dll!juce::Component::internalMouseDown(const int x=211, const int y=56) Line 2558 + 0x16 bytes C++
test_debug.dll!juce::ComponentPeer::handleMouseDown(int x=211, int y=56, const int64 time=1221827097483) Line 250 C++
test_debug.dll!juce::Win32ComponentPeer::doMouseDown(const int x=558, const int y=464, const unsigned int wParam=2) Line 1404 C++
test_debug.dll!juce::Win32ComponentPeer::peerWindowProc(HWND
* h=0x00071080, unsigned int message=516, unsigned int wParam=2, long lParam=30409262) Line 1896 C++
test_debug.dll!juce::Win32ComponentPeer::windowProc(HWND__ * h=0x00071080, unsigned int message=516, unsigned int wParam=2, long lParam=30409262) Line 1841 + 0x18 bytes C++
[/code]


#6

Oh, that’s particularly nasty, because once the comp has been deleted, control will return to the place after you called the modal function, and at that point you’ll have a whole stack full of deleted components. I think the only fix would be to defer deleting the plugin’s editor component if there’s currently a modal component active, but to send a message that will delete it at a later time.

Ok, try the version that I’ve just checked-in - it’s completely untested, but might work!


#7

thanks but it doesn’t help, it seems that Component::getCurrentlyModalComponent() doesn’t recognize the popup-menu, even if i remove PopupMenu::dismissAllActiveMenus(); and put it behind the function.
I made some DBG-statements before and after popUpMenu.show() and i found out that the the host calls effEditClose, just after the popMenu is disappeared and before popUpMenu.show() exists.

this is the order:

Enter EnvelopeBox::mouseDown
PopMenu Start
modalComponentStack.size=0
Enter Modal State
modalComponentStack.size=1
modalComponentStack.size=2 (opening PopUp Sub menu)
modalComponentStack.size=1

Host Calls effEditClose and modalComponentStack.size=0
Delete Editor
PopMenu.show() returns
–> Crash


#8

But with my changes, the deleteeditor call shouldn’t actually delete the editor yet, that should only happen later on, using a timer. Are you sure you correctly applied the change?


#9

yes i’m sure. The problem is that Component::getCurrentlyModalComponent() returns zero and the editor will not be closed later.
If i modify the code that the Gui always will be closed later, this will also cause problems, an empty plugin-window will be shown.


#10

Then I’m stumped - I don’t see how the current modal comp can be 0, if you move the dismissAllActiveMenus() call to be after checking for it…


#11

Hi Jules, my assumption is, after or while the PopupMenuWindow will be closed, just exactly in the same moment/position, there must be a call to the OS (which closes the popup-window), which might changes the main window focus, and causes cubase to close the plugin-window.

So the juce internal modalComponentStack is empty, but the window which contains the popUpMenu will be closed a little little moment later, and at this moment the callback isn’t finished.

The issue doesn’t happens every time, but ca. every third try.


#12

Well, if it’s using win32 calls to delete the window, then I guess there’s not much you can do about that…