Crash deleting instances of plugin in ableton

Only tested this on a Mac so far. Steps to reproduce:

  1. start a new, empty set in live 8
  2. load an instance of my VSTi to an empty track
  3. duplicate the track 5+ times
  4. select the column header of the rightmost of the new tracks
  5. rapidly press the delete key to start deleting the new tracks

Live will crash, and it appears that what’s happening is that it’s trying to paint the plugin window of the newly displayed tracks as the tracks are being deleted. It looks to me as if the VST wrapper is trying to keep a message loop running for a deleted window but I don’t know Cocoa at all so that’s just a guess. The AU version of the plugin doesn’t exhibit this bug.

Stack trace as follows:
Thread 0 Crashed: Dispatch queue:
0 0x00864821 0x1000 + 8796193
1 0x0158283d std::out_of_range::~out_of_range() + 4204815
2 0x01588a9f std::out_of_range::~out_of_range() + 4230001
3 0x014a4511 std::out_of_range::~out_of_range() + 3294691
4 0x014adb20 std::out_of_range::~out_of_range() + 3333106
5 0x014ac965 std::out_of_range::~out_of_range() + 3328567
6 0x92fabd9e -[NSMenu _enableItem:] + 651
7 0x92faf09c -[NSCarbonMenuImpl _carbonUpdateStatusEvent:handlerCallRef:] + 527
8 0x92facc61 NSSLMMenuEventHandler + 404
9 0x92a07ecf DispatchEventToHandlers(EventTargetRec*, OpaqueEventRef*, HandlerCallRec*) + 1567
10 0x92a07196 SendEventToEventTargetInternal(OpaqueEventRef*, OpaqueEventTargetRef*, HandlerCallRec*) + 411
11 0x92a29a07 SendEventToEventTarget + 52
12 0x92a55fd3 SendHICommandEvent(unsigned long, HICommand const*, unsigned long, unsigned long, unsigned char, void const*, OpaqueEventTargetRef*, OpaqueEventTargetRef*, OpaqueEventRef**) + 448
13 0x92a7fa9b UpdateHICommandStatus + 69
14 0x92a7f953 EnableMenu(MenuData*, OpaqueEventTargetRef*, unsigned short, unsigned char, CheckMenuData*, unsigned long, double) + 95
15 0x92a7e65c Check1MenuForKeyEvent(MenuData*, CheckMenuData*) + 1412
16 0x92a7d801 CheckMenusForKeyEvent(MenuData*, CheckMenuData*) + 835
17 0x92a7d42e _IsMenuKeyEvent(MenuData*, OpaqueEventRef*, unsigned long, MenuData**, unsigned short*) + 773
18 0x92a7d0ef IsMenuKeyEvent + 102
19 0x930b132f -[NSCarbonMenuImpl _menuItemWithKeyEquivalentMatchingEventRef:] + 307
20 0x930b1081 _NSFindMenuItemMatchingCommandKeyEvent + 295
21 0x92fa6293 _NSHandleCarbonMenuEvent + 526
22 0x92f7ad3e _DPSNextEvent + 2304
23 0x92f79fce -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 156
24 com.kuniklo.JSynth 0x27ca2b33 juce::MessageManager::runDispatchLoopUntil(int) + 345 (
25 com.kuniklo.JSynth 0x27ccc5d9 juce::detachComponentFromWindowRef(juce::Component*, void*) + 698 (
26 com.kuniklo.JSynth 0x27cc7f01 JuceVSTWrapper::deleteEditor(bool) + 323 (juce_VST_Wrapper.cpp:1104)
27 com.kuniklo.JSynth 0x27ccaaf6 JuceVSTWrapper::dispatcher(int, int, int, void*, float) + 608 (juce_VST_Wrapper.cpp:1171)
28 com.kuniklo.JSynth 0x27cc3410 AudioEffect::dispatchEffectClass(AEffect*, int, int, int, void*, float) + 160 (audioeffect.cpp:32)
29 0x000a2e9e 0x1000 + 663198
30 0x000cb3d6 0x1000 + 828374

Damn. Yes, if you look at the comments in detachComponentFromWindowRef(), you’ll see my explanation of why it does that… Not really sure what a good workaround for this would be!

Thanks for the quick reply. I guess it’s sort of a “damned if you do, damned if you don’t” situation.

I tried this with several non-Juce plugins and didn’t get crashes so there must be some way to make it work but unfortunately I’m too new to both VST and Cocoa to make any useful suggestions. It’s interesting that the AU version seems ok though.

Yeah, it’s all to do with that pesky Cocoa window and the way obj-c references are left hanging around. AUs won’t have the problem because they use NSViews instead. VSTs have to bodge it with an NSWindow to get everything to work in old Carbon apps.

Very hard to think of anything I could do to avoid this… Perhaps using a modal component could block the menu events and stop the command getting performed…?

[code]void detachComponentFromWindowRef (Component* comp, void* nsWindow)
… etc…

Component dummy;
dummy.enterModalState (true, 0);

for (int i = 20; --i >= 0;)
    MessageManager::getInstance()->runDispatchLoopUntil (1);


Tried this but I’m getting the same crash. Forgive the naive question, but what makes Juce different from other VSTs here? Do they mostly use Carbon and the tricky bit is the Cocoa/VST interaction specific to Juce or have they just figured out some other workaround to this problem?

They mostly use carbon, I think. Or the really old VSTGUI ones just draw directly into the host’s window and avoid any kind of windowing altogether! I think the new VSTSDK might be switching to do it properly with NSViews, so we’ll need to support that, but few hosts will support it yet.

I'm regressing some old bugs and came to this one.  It no longer appears to be a problem with Live 9 and recently compiled Juce plugins. 

I tested Aalto 1.4.1 on Mac OS 10.8.4 with Live 9, and beat on it rather thoroughly. The windows all delete and draw as expected with no crashes or other problems.