Phew, had fun tracking this down. I think its a Mac only issue. When quitting my app would randomly(1 in 50 or so) throw an assert in
jassert (objectsToDelete.size() == 0);
Looking at the objectsToDelete object showed 1 item in it. I eventually tracked it down to an instance of MessageManager being re-created… Here is a few callstacks
#0 juce::MessageManager::MessageManager (this=0x1085c1f0) at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/events/juce_MessageManager.cpp:60
#1 0x0173b6cc in juce::MessageManager::getInstance () at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/events/juce_MessageManager.cpp:76
#2 0x017171b4 in juce::MessageManager::doPlatformSpecificShutdown () at juce_mac_MessageManager.mm:317
#3 0x0173b16b in juce::MessageManager::~MessageManager (this=0x213e520) at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/events/juce_MessageManager.cpp:69
#4 0x016654b5 in juce::DeletedAtShutdown::deleteAll () at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/application/juce_DeletedAtShutdown.cpp:79
#5 0x01613987 in juce::shutdownJuce_GUI () at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/application/juce_Application.cpp:343
#6 0x01613a6e in juce::JUCEApplication::shutdownAppAndClearUp () at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/application/juce_Application.cpp:260
#7 0x01614008 in juce::JUCEApplication::main (commandLine=@0xbffff64c, app=0x21311c0) at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/application/juce_Application.cpp:227
#8 0x01614206 in juce::JUCEApplication::main (argc=1, argv=0xbffff6fc, newApp=0x21311c0) at /Volumes/Reznor/JUCE/build/macosx/../../src/juce_appframework/application/juce_Application.cpp:288
#9 0x0006e73b in main (argc=1, argv=0xbffff6fc) at /Volumes/Reznor/SM/JUCE_MiniMiner/MiniMiner/MiniMinerMain.cpp:124
The problem appears to be here
void MessageManager::doPlatformSpecificShutdown()
{
[[NSRunLoop currentRunLoop] cancelPerformSelectorsWithTarget: juceAppDelegate];
[[NSNotificationCenter defaultCenter] removeObserver: juceAppDelegate];
// Annoyingly, cancelPerformSelectorsWithTarget can't actually cancel the messages
// sent by performSelectorOnMainThread, so need to manually flush these before quitting..
for (int i = 100; --i >= 0 && numPendingMessages > 0;)
{
flushingMessages = true;
getInstance()->runDispatchLoopUntil (10);
}
jassert (numPendingMessages == 0); // failed to get all the pending messages cleared before quitting..
[juceAppDelegate release];
juceAppDelegate = 0;
}
getInstance() is creating a new instance when there are messages in the queue.
However
MessageManager::~MessageManager() throw()
{
jassert (instance == this);
instance = 0;
deleteAndZero (broadcastListeners);
doPlatformSpecificShutdown();
}
Has already set the instance to NULL.
I think changing the following will work
MessageManager::~MessageManager() throw()
{
jassert (instance == this);
deleteAndZero (broadcastListeners);
doPlatformSpecificShutdown();
instance = 0;
}
PHEW!