Hey Jules,
the bug spotter has another one:
juce_mac_MessageManager.mm: doPlatformSpecificShutdown() crashes Logic when you open up a plugin, close the GUI and afterwards remove the plugin from the insert -> BAD EXEC.
This doesn’t happen with the demo plugin but with any more advanced juce plugin I’ve checked.
But don’t worry, I already found a solution for this, you just have to put it to the official tip.
First the original version which leads to the crash:
// Annoyingly, cancelPerformSelectorsWithTarget can't actually cancel the messages
// sent by performSelectorOnMainThread, so need to manually flush these before quitting..
juceAppDelegate->flushingMessages = true;
for (int i = 100; --i >= 0 && numPendingMessages > 0;)
{
const ScopedAutoReleasePool pool;
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
beforeDate: [NSDate dateWithTimeIntervalSinceNow: 5 * 0.001]]; //!!!!!!! CRASHES HERE BECAUSE "numPendingMessages" ISN'T DECREASED IN TIME !!!!!!!!!!!!!!
}
[juceAppDelegate release];
juceAppDelegate = 0;
}
Hmm. Interesting, but your fix looks a bit suspicious to me. Each time the run loop is invoked, it may or may not dispatch one or more of those messages, so to decrement the counter each time means that it’s not really a true reflection of how many messages are still pending. And if any of those messages are left behind to get delivered after the module is unloaded, it’ll definitely crash.
It’s hard to figure out what’s actually happening, but perhaps the cancelPerformSelectorsWithTarget call really does cancel them, despite what the docs say…? That’d explain why the numPendingMessages count doesn’t go down. If that’s the case, then it’d be ok to remove the entire loop, but that doesn’t sound right to me.
Yes maybe it was a little too late yesterday. I looked at it again this morning and it looked spuspicious to me, too. It’s right, doing it this way was like removing the entire loop. It seems like a timing problem to me.
Here is the relevant part of the (reproducable) crashlog but I don’t think that it helps much :
[code]
Process: Logic Pro [3935]
Path: /Applications/Logic Pro.app/Contents/MacOS/Logic Pro
Identifier: com.apple.logic.pro
Version: 8.0.2 (1502.22)
Build Info: Logic-15022200~9
Code Type: X86 (Native)
Parent Process: launchd [781]
Interval Since Last Report: 10581 sec
Crashes Since Last Report: 237
Per-App Interval Since Last Report: 5107 sec
Per-App Crashes Since Last Report: 3
Date/Time: 2009-11-13 11:13:16.343 +0100
OS Version: Mac OS X 10.5.8 (9L31a)
Report Version: 6
Anonymous UUID: 65B5460D-97A7-4D4E-B4DA-ECF2AAB099ED
Forgot to mention, removing the entire loop works fine, too.
EDIT: No, sorry, doesn’t work with VST. Please don’t care about this thread for a while, I will do more tests before I get back with better infos about what’s happening.
I’m not able to find a solution for this.
So here is the current state:
The crash only happens in Logic, when plugins are opened -> the gui is closed -> the plugin is removed.
If “MessageManager::doPlatformSpecificShutdown()” is entered with “numPendingMessages = 0” then there are no problems, that’s the reasen why the juceDemoPlugin doesn’t crash (it enters with no pending messages).
In AU Lab and Live, there are no crashes with pending messages.
If I set a breakpoint somewhere in juce_mac_MessageManager.mm:
- (void) customEvent: (id) n
{...}
and exeucte the same code then there is no crash with the same setup that crashes without this breakpoint. For this reason I assume that it is a timing problem.
If I remove the entire loop in “MessageManager::doPlatformSpecificShutdown()” there is no crash in logic, AU Lab and Live when using the AU plugin but now the VST Version crashes Live on opening the Live app.
I have no idea how to find a solution that works well in every environment.
I think I need some help to sort this out.
It’s a very difficult problem. If only the cancelPerformSelectorsWithTarget call actually worked, it’d all be easy, but there’s just no way of actually removing those events from the queue.
I wonder if there’s a way of rewriting all the messaging to avoid obj-c and use CFRunLoops instead… Really can’t think of any other way to make it safe.
Damn, I didn’t expect that it would be this complicated. Unfortunately I don’t have any experience with CFRunLoops and it’s messaging system, so I don’t think it would be a good idea to do it on my own. If there’s anything else I can help with or if you have another idea what I could try, then let me know.
I think it’s probably possible using a timer and keeping the messages in a local array… I’ll have a go, because I can’t think of any other way round this, and at least it’ll remove that messy clear up loop from the shutdown.
As I mentioned, it will only crash if it enters “doPlatformSpecificShutdown()” with numPendingMessages > 0. If your plugin will never have any pending messages at this point then you’re fine.
Could you set a breakpoint at the beginning of “doPlatformSpecificShutdown()” and check if there are pending messages when it hits the breakpoint? If so, then maybe it works with Logic 9 and OSX 10.6.
My latest check-in uses a completely new method for dispatching the messages on OSX, so give it a go… Should definitely avoid any of these nasty shutdown issues.