[launchd-dev] ~/LaunchAgent + KeepAlive=true = Login Jail

James Bucanek subscriber at gloaming.com
Thu Jan 31 10:17:30 PST 2008

Quinn <mailto:eskimo1 at apple.com> wrote (Tuesday, January 29, 
2008 3:45 AM -0000):
>A better solution is to look at the kAEWhyAmIBeingLoggedOutAttr
>('why?') attribute of the kAEQuitApplication ('quit') Apple event. If
>you're being quit by loginwindow, this will contain one of four
>different codes indicating why (kAEQuitAll, kAEShutDown, kAERestart,
>kAEReallyLogOut).  If you're being quit by the user (or by an
>AppleScript or any other 'quit' Apple event mechanism), this attribute
>won't be present.

Thanks, Quinn. That's a excellent solution.

I did, indeed, search the documentation, developer.apple.com, 
and the various lists for any mention of determining if a Quit 
event was being sent because of a shutdown, restart, or logout. 
So this isn't just undocumented, it's below the radar.

Inside Apple, you're probably using header files we don't have. ;)

grepping of all of the 10.4 & 10.5 SDK header files, I can't 
find any declaration for kAEWhyAmIBeingLoggedOutAttr. However, 
there is a declaration for kEventParamReason = 'why?' in 
CarbonEvents.h. That's good enough for me.

So I think I have this working nicely now. I added the 
SuccessfulExit=false to the KeepAlive property and added the 
following code to my Cocoa application

static void dirtyExit( void )
     // At the very last moment possible, force an abnormal exit

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender
#pragma unused(sender)

     // Find out if the application is quitting for a Log Out, 
Shutdown, or Restart
     // This has to be detemined in applicationShouldTerminate: 
becuase the AppleEvent goes away soon.
     NSAppleEventDescriptor* quitEventDesc = 
[[NSAppleEventManager sharedAppleEventManager] currentAppleEvent];
//  NSLog(@"%p%s %@",self,__func__,quitEventDesc);
     NSAppleEventDescriptor* whyDesc = [quitEventDesc attributeDescriptorForKeyword:kEventParamReason];
     OSType why = [whyDesc typeCodeValue];
     if ( !(why==kAEQuitAll || why==kAEShutDown || 
why==kAERestart || why==kAEReallyLogOut) )
         //NSLog(@"application will exit abnormally");
         // If the monitor is not exiting cleanly, register a 
program exit handler that will throw an error following normal termination

     return (YES);

Thanks again. I'll file a bug report on the documentation.

James Bucanek

More information about the launchd-dev mailing list