I'm working on a cross-platform framework, and am trying to finish up a 
parallel but portable message dispatch mechanism in the framework when its main 
thread is running in NSApplication.  To this end, I'm using 
CFRunLoopSourceCreate/CFRunLoopAddSource as the framework message trigger 
because I can safely trigger the source from other threads using that 
mechanism.  It is working nicely, except for the quit sequencing.  In 
Linux/GTK, the analogous mechanism is installing the read end of a pipe using 
g_io_add_watch, writing to the pipe when a message is posted to my framework, 
and it works perfectly.

For the Cocoa implementation, I have implemented an applicationShouldTerminate 
app delegate notification handler which posts a quit request to my framework 
(triggering it by way of the CFRunLoopSource) and returns NSTerminateCancel.  
That last detail is very unfortunate, but if I return NSTerminateLater the app 
goes into a modal state and neglects the CFRunLoop, with my framework's quit 
request not being received as a consequence.

If I use the dock's application menu to issue a quit request, the 
kAEQuitApplication Apple event ends up in applicationShouldTerminate, then 
after returning NSTerminateCancel the framework message is processed by way of 
the run loop source.  If the application decides that it can indeed quit, it 
sends [ns_application stop: ns_application] and the application quits 
successfully, returning through __CFRunRoolRun, ..., _DPSNextEvent, ..., 
-[NSApplication run], back out to NSApplicationMain.  All good...

The problem arises if the application, in the course of doing its thing decides 
to quit where its activity has been recently isolated to my framework through  
the CFRunLoop source.  My custom quit request message is handled in that 
context, and I send [ns_application stop: ns_application], just as if the quit 
request had originated from an Apple event.  Even though the call stack looks 
identical in these two cases (apple event from dock quit menu item or 
internally initiated quit), the run loop doesn't actually quit in the latter 
case.  I tried following sending the stop message with an explicit call to 
CFRunLoopStop, with no luck.  There seems to be something special about the 
context of having received kAEQuitApplication.

Based on these observations, I tried having my framework, upon making a quit 
decision, post kAEQuitApplication to itself.  Unfortunately, AESendMessage 
crashes inside of findPortByPSN -> AECSD_LookupAppleEventPortByPSN -> mach_msg 
-> mach_msg_trap.  I speculate that AESendMessage normally uses two IPC 
transactions, one to get the port and one to post to the port.  Speculating 
again, but because the application is trying to talk to itself, it can't 
respond to its own request for the port and the transaction breaks down.

Does anyone have a suggestion for a better way to solve the won't quit problem, 
or a better (thread safe) mechanism for triggering my framework than a 
CFRunLoop source?

Also, a somewhat off-topic question from an objective-C newcomer.  I see this 
in the successful quit case:

_DPSNextEvent -> AEProcessEvent -> ... -> -[NSApplication _shouldTerminate] -> 
-[_docController:shouldTerminate:] -> -[NSAppDelegate 
applicationShouldTerminate:]

I wanted to try simply posting (asynchronously) a quit request right in the Mac 
Objective-C framework, specifically to _shouldTerminate, but I don't see how to 
do that.  The only built-in Objective-C asynchronous messaging I found involved 
NSNotificationQueue, and it didn't seem like the right way to go.  I would 
speculate that NSNotificationQueue would have to use a similar triggering 
mechanism to what I'm doing with the CFRunLoop source, and would break in the 
same manner.  Am I wrong about NSNotificationQueue or overlooking a built-in 
Objective-C feature here?  If it exists, it seems like that would also work 
around the modal state neglects run loop source problem I described earlier 
when returning NSTerminateLater from applicationShouldTerminate.

Thanks,
Brian Tietz


      
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to