Nasty DeletedAtShutdown::deleteAll() assert

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!

You can recreate by simply commented out the for() loop

[code]
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;

}[/code]

Agh! Nice bug-hunting there. Yes, looks like your suggested fix is spot-on - I’ll get that in there right away!

Thanks!

agggh, I was getting this and was too embarrassed to mention it ! Though I was doing some thing silly…

Thanks for fixing!