Delayed quit


#1

I’ve got an application that calls JUCEApplication::quit() when it sees a USB device pulled out. On Windows it works great. On the Mac the application stays on the screen until I move the mouse or hit a key on the keyboard. It is as if the quit message to the Window is not being handled until some other messages get put the Window’s message queue?

My sloppy fix is to hide the window after calling JUCEApplication::quit() (setVisible(false)). This works except that the application still appears in the dock until you move the mouse.

Any ideas?


#2

Is this in an old version? Sounds like something I fixed months ago…


#3

I just upgraded to 1.50.

I first discovered this bug a month ago and I thought I had discovered mention of it and a pending fix in the forum, but after the upgrade did not fix the problem, I spent a bunch of time searching the forums and could not find the thread I was looking for, so I started a new one.


#4

Are you running a modal loop? I suppose it’s possible that that could sit there waiting in between messages…


#5

No, no modal loop. My main window is a ChangeListener. The quit happens when a separate thread sends a change message (sendChangeMessage). The main window’s changeListenerCallback() gets called and then calls JUCEApplication::quit().


Juce Application steals focus on exit
#6

Very odd. Does this change help, in juce_mac_MessageManager.cpp:

[code]void MessageManager::stopDispatchLoop()
{
quitMessagePosted = true;
[NSApp stop: nil];
[NSApp activateIgnoringOtherApps: YES]; // (if the app is inactive, it sits there and ignores the quit request until the next time it gets activated)

Message* const m = new Message (quitMessageId, 0, 0, 0);
m->messageRecipient = 0;
postMessageToQueue (m);

}
[/code]

?


#7

Nope


#8

ok… this?

void MessageManager::stopDispatchLoop() { quitMessagePosted = true; [NSApp stop: nil]; [NSApp activateIgnoringOtherApps: YES]; // (if the app is inactive, it sits there and ignores the quit request until the next time it gets activated) [NSApp sendEvent: [NSEvent otherEventWithType: NSPeriodic location: NSMakePoint (0, 0) modifierFlags: 0 timestamp: nil windowNumber: 0 context: 0 subtype: 0 data1: 0 data2: 0]]; }


#9

Sorry, that didn’t help either.


#10

Ok. This definitely works:

void MessageManager::stopDispatchLoop() { quitMessagePosted = true; [NSApp stop: nil]; [NSApp activateIgnoringOtherApps: YES]; // (if the app is inactive, it sits there and ignores the quit request until the next time it gets activated) [NSEvent startPeriodicEventsAfterDelay: 0 withPeriod: 0.1]; }


#11

That one fixed it!


#12

Quite strangely, when calling JUCEApplication::quit() at the end of another thread (namely, a boost::thread), at the thread destruction I get the following crash on mac: [code]EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000024

And the crashed thread (the one which comes to its termination) 's stack looks like
0 libobjc.A.dylib 0x9130ff87 obj_msgSend + 23
1 libSystem.B.dylib 0x9a527c89 _pthread_tsd_cleanup + 190
2 libSystem.B.dylib 0x9a527836 _pthread_exit + 154
3 libSystem.B.dylib 0x9a51f0de thread_start + 34[/code]

If I comment the line

Then the crash disappears… any idea how to circumvent this?


#13

Maybe not so strange… maybe add [NSEvent stopPeriodicEvents]; after my quit() call? It seems to resolve the issue.


#14

Well, the quit() method wasn’t really designed to be called by a background thread. I think my own code is probably thread-safe, but I can’t vouch for the safety of the OS calls that it uses…


#15

Almost exactly a year later, it seems I’m running into the same issue.

So what IS the right way to quit a Juce application from a background thread? Or, wait, do you just mean to call it from the MessageManager thread? No, that doesn’t work…


#16

I’d suggest making it fire a CallbackMessage that calls the normal quit method.


#17

He shoots - he scores! Another goal for Storer!!

That worked right the first time, and everything shuts down just right now.

It’s very interesting to me that I could be the first person to run into this - even knowing the answer I don’t see another reference to this online. It would seem obvious that sometimes people would want to shut down from some other thread but few people are doing it - it shows you how similar most people’s applications are! (And why I always get into trouble - because I don’t think the same as most people. This application is being controlled over a socket connection…)

Consider perhaps adding an assert to make sure that you’re on the right thread when you call JUCEApplication::quit…?


#18

Yep, good idea!