[launchd-dev] launchctl unload not working

Kevin Van Vechten kvv at apple.com
Wed Nov 28 23:08:49 PST 2007


I recommend reading the "Daemonomicon" <http://developer.apple.com/technotes/tn2005/tn2083.html#SECDAEMONOMICON 
 >.

Short summary pertinent to your symptoms:

- Root (uid 0) launchd loads jobs from LaunchDameons directories.  Use  
`sudo launchctl` to communicate with it.
- Per-user (uid 501) launchd loads jobs from LaunchAgents  
directories.  Use `launchctl` to communicate with it.
- Per-user launchd ignores the UserName key because it does not have  
the privilege to execute as any other user than the current user.
- Per-user mach bootstrap is a sub-bootstrap of the root mach  
bootstrap: agents can lookup daemons, but daemons cannot lookup agents.

- Kevin


On Nov 28, 2007, at 10:28 PM, James Bucanek wrote:

> Greetings,
>
> I'm having a number of issues with launchd, particularly under  
> Leopard. (Most, if not all, of this works just fine under Tiger.) My  
> current, and most pressing issue, is trying to replace a daemon when  
> the user upgrades their software.
>
> Here's what I've got running
>
> - A daemon is installed in /Library/LaunchDaemons/ 
> QRecallScheduler501.plist. I install the file by writing the plist  
> then executing 'launchctl load /path-to-plist' as root. The .plist  
> file has the UserName property set to an individual user.
>
> This has been working (mostly) until I need to upgrade the user's  
> software. I've tried various techniques, but the one I'm using now  
> which I think should work doesn't.
>
> Setup (if this makes any difference): The path to the daemon is a  
> symbolic link to the actual binary in my application bundle. When  
> the application is upgraded (via Sparkle), the application bundle is  
> replaced with the new application bundle containing an updated daemon.
>
> Step #1: Run 'launchctl unload -w /path-to-plist' as root. I wait  
> for launchctl to return and then wait for the daemon to terminate.
>
> Step #2: Delete the .plist at /Library/LaunchDaemons/ 
> QRecallScheduler501.plist.
>
> Step #3: Write a new .plist at /Library/LaunchDaemons/ 
> QRecallScheduler501.plist
>
> Step #4: Run 'launchctl load /path-to-plist' as root. Wait for  
> launchctl to finish.
>
> Here's what happens:
>
> In step #1, launchctl returns with a status of 0. The daemon  
> receives a SIGTERM and shuts down (2-3 seconds).
>
> IMMEDIATELY, launchd starts the new deamon. I can only assume  
> because the location of the updated binary is the same as the old  
> one that was just terminated.
>
> Steps #2 and #3 delete and rewrite the .plist.
>
> Step #4 runs 'launchctl load' which returns with a status of 0. What  
> I get in the console log is
>
> 11/28/07 4:09:44 PM [0x0-0x1e01e].com.qrecall.client[145] launchctl:  
> Error unloading: com.qrecall.scheduler
> 11/28/07 4:09:56 PM com.apple.launchd[62] (com.qrecall.scheduler. 
> 501) Ignored this key: UserName
>
> Contrary to the second error, the daemon is run with a UID of 501  
> (which is correct -- the daemon will terminate if it's started as  
> root).
>
> The new daemon is then repeatedly restarted. (The daemon checks for  
> a duplicate running instance of itself and terminates immediately if  
> it's already running.)
>
> 11/28/07 4:09:57 PM com.apple.launchd[62] (com.qrecall.scheduler. 
> 501) Throttling respawn: Will start in 10 seconds
> 11/28/07 4:10:07 PM com.apple.launchd[62] (com.qrecall.scheduler. 
> 501) Throttling respawn: Will start in 10 seconds
> 11/28/07 4:10:17 PM com.apple.launchd[62] (com.qrecall.scheduler. 
> 501) Throttling respawn: Will start in 10 seconds
> 11/28/07 4:10:27 PM com.apple.launchd[62] (com.qrecall.scheduler. 
> 501) Throttling respawn: Will start in 10 seconds
>
> The really bad part is the instance of the daemon that is running  
> does not seem to be running in the correct environment/namespace.  
> When it launches a sub-process it attempts to connect with it using  
> Mach ports; The connection fails. Restarting the OS doesn't fix the  
> problem.
>
> I think the problem is that (in Leopard) there seems to be two  
> instances of launchd running: One as root and one as user 501. But  
> I'm getting very confused as to which one I should be trying to deal  
> with.
>
> I changed the code to call launchctl while running as user 501. That  
> sometimes works and sometimes doesn't. If I can get the daemon to  
> stop and issue 'launchctl load /...' as user 501, the daemon starts  
> working: specifically, it can communication with the sub-processes  
> that it starts. Once started using 'launchctl' as user 501 it can be  
> stopped again using launchctl as 501. But after a restart, it's  
> running in the wrong namespace again and I have to perform a 'sudo  
> launchctl unload' to get it to stop.
>
> So after an entire day, I'm really confused as to what launchctl  
> commands I should be issuing to replace a running deamon, in what  
> order, and using what UID.
>
> James
> -- 
> James Bucanek
>
> _______________________________________________
> launchd-dev mailing list
> launchd-dev at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo/launchd-dev



More information about the launchd-dev mailing list