An agent with Keep-Alive set to true (in this agent's plist)
Hello! I would like to have my application launched all the time - even when user makes it quit, it relaunches itself (this is a kind of child protection system). OS X has exactly what i need - an agent, with Keep-Alive set to "true" in this agent's .plist file (i chose agent - because i need an interface for this application). The problem is when the system tries to quit (reboot/shut down), my agent "cancels the shut down" (it behaves exactly like i'd return "NO" in -applicationWillClose method of the Application delegate, except the fact that i am not returning anything there). I tried to set up "throttle respawn" time for the agent to 20 seconds in a plist file (it is not necessary for the agent to be restarted immediately after 1 second for me), but (as it seems) the "respawning" happen not necessarily in 20 seconds, but within 0-20 seconds interval. Which leads again to "the application MyAgent has cancelled the restart" when i want to shut down the machine. Is there any way to solve this issue? Thank you Nick
On 2011 Jun 09, at 14:04, Nick wrote:
Is there any way to solve this issue?
This may not be a "solution", but just to clarify, I think the problem comes about because the process you're keeping launched all the time is an *application*. I use "KeepAlive" for a command-line tool and don't have this problem. It's possible that Apple designed it this way on purpose; indeed it would be quite odd to have an *app* which the user could not quit. And if your app is, as you say,
(this is a kind of child protection system)
it seems that it might be better off as a background process which the child does not see. Alternatively, you could write a little command-line tool which would do what launchd does, watching for your app to quit (this can be done by registering for NSWorkspaceDidTerminateApplicationNotification and entering a run loop) and then relaunching your app whenever it quits. Then you would have launchd launch this command-line tool instead of your app. I've written such a tool which watches for apps to quit. Here is its main(): int main(int argc, const char *argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init] ; [[NSUserDefaults standardUserDefaults] addSuiteNamed:@"com.myCompany.myApp"] ; // Create a run loop NSRunLoop* runLoop = [NSRunLoop currentRunLoop] ; // Create a Quatcher, which will add an observer Quatcher* quatcher = [[Quatcher alloc] init] ; [runLoop run] ; [quatcher release] ; [pool release] ; return 0 ; } The "Quatcher" class is my "Quit Watcher". I'll post its code if you request it. Think about your design. You probably don't want an app that never quits. What you probably want is an app which sets some user defaults, loads a launchd task to "KeepAlive" a helper tool, and is then quit. Your app's package will contain the kept-alive background helper tool which will do the work 24/7 as directed by the app's preferences. It's a little more tricky design. Read the message I posted yesterday in answer to a similar question on cocoa-dev: http://lists.apple.com/archives/Cocoa-dev/2011/Jun/msg00245.html
Hi Jerry, Thank you for the response. But what differs an application from a command line application? How launchd realizes it's an application? By presence of an application bundle? Of a plist? Instantiating NSApplication object? Some other ways? 2011/6/10 Jerry Krinock <jerry@ieee.org>
On 2011 Jun 09, at 14:04, Nick wrote:
Is there any way to solve this issue?
This may not be a "solution", but just to clarify, I think the problem comes about because the process you're keeping launched all the time is an *application*. I use "KeepAlive" for a command-line tool and don't have this problem.
It's possible that Apple designed it this way on purpose; indeed it would be quite odd to have an *app* which the user could not quit. And if your app is, as you say,
(this is a kind of child protection system)
it seems that it might be better off as a background process which the child does not see.
Alternatively, you could write a little command-line tool which would do what launchd does, watching for your app to quit (this can be done by registering for NSWorkspaceDidTerminateApplicationNotification and entering a run loop) and then relaunching your app whenever it quits. Then you would have launchd launch this command-line tool instead of your app.
I've written such a tool which watches for apps to quit. Here is its main():
int main(int argc, const char *argv[]) { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init] ;
[[NSUserDefaults standardUserDefaults] addSuiteNamed:@"com.myCompany.myApp"] ;
// Create a run loop NSRunLoop* runLoop = [NSRunLoop currentRunLoop] ;
// Create a Quatcher, which will add an observer Quatcher* quatcher = [[Quatcher alloc] init] ;
[runLoop run] ;
[quatcher release] ; [pool release] ;
return 0 ; }
The "Quatcher" class is my "Quit Watcher". I'll post its code if you request it.
Think about your design. You probably don't want an app that never quits. What you probably want is an app which sets some user defaults, loads a launchd task to "KeepAlive" a helper tool, and is then quit. Your app's package will contain the kept-alive background helper tool which will do the work 24/7 as directed by the app's preferences. It's a little more tricky design. Read the message I posted yesterday in answer to a similar question on cocoa-dev:
http://lists.apple.com/archives/Cocoa-dev/2011/Jun/msg00245.html
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
On 2011 Jun 10, at 01:54, Nick wrote:
But what differs an application from a command line application? How launchd realizes it's an application? By presence of an application bundle? Of a plist? Instantiating NSApplication object? Some other ways?
That's an interesting question; I really don't know. Command-line tools can have embedded plists (and must, for code signing), but there are many differences which launchd could use. Most likely are the keys CFBundlePackageType=APPL and NSPrincipalClass=NSApplication.
On 10 Jun 2011, at 01:54, Nick wrote:
But what differs an application from a command line application? How launchd realizes it's an application?
It's not launchd that realises that it's an app, it's loginwindow. When you attempt to log out (which the initial step in restart and shutdown), loginwindow asks each of the app's to quit cleanly. If an app can't quit, loginwindow prevents the log out. You need to get your app out of that path, and the best way to do that is to prevent loginwindow from seeing your agent as a GUI app. S+E -- Quinn "The Eskimo!" <http://www.apple.com/developer/> Apple Developer Relations, Developer Technical Support, Core OS/Hardware
Thanks Quinn, What i wanted to do - is to have an application similarly to finder remain in Dock (this is a parental control app that has to have an icon in Dock showing the status of the daemon in that icon) without user being able to Quit it from the dock Menu (when one command-clicks on this icon with the mouse). I described this issue here: http://stackoverflow.com/questions/6330518/how-to-make-a-finder-like-dock-me... I desperately was looking for ways, how did Apple eliminate that "Quit" (and "Options") item from the Finder's Dock menu (it seems to me it is either hardcoded or hidden deep in plists, in either way not documented). That's why i'm searching for workarounds like - an agent without "LSUIItem" set to true - but, as i described earlier, the computer simply didn't shut down. To solve this issue, as Jerry suggested, I delegated this "dock icon" to a special "Docklet" application that only displays an icon in dock when its launched, and the Agent was to restart this "Docklet": if a user quits this Dock application, the supporting agent restarts this "Docklet" application automatically. And again, it failed - the shutdown is being cancelled by this "Dock app" this time. I am aware of that this is not a "mac way" to display status in Dock rather than a status bar, but I can't help it as the boss does not like little icon in status bar that my agent displays currently. And since Finder works like that I was hoping an another application can. 2011/6/14 Quinn "The Eskimo!" <eskimo1@apple.com>
On 10 Jun 2011, at 01:54, Nick wrote:
But what differs an application from a command line application? How launchd realizes it's an application?
It's not launchd that realises that it's an app, it's loginwindow. When you attempt to log out (which the initial step in restart and shutdown), loginwindow asks each of the app's to quit cleanly. If an app can't quit, loginwindow prevents the log out. You need to get your app out of that path, and the best way to do that is to prevent loginwindow from seeing your agent as a GUI app.
S+E -- Quinn "The Eskimo!" <http://www.apple.com/developer/> Apple Developer Relations, Developer Technical Support, Core OS/Hardware
_______________________________________________ launchd-dev mailing list launchd-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/launchd-dev
participants (3)
-
Jerry Krinock
-
Nick
-
Quinn "The Eskimo!"