[launchd-dev] launchctl unload not working
James Bucanek
subscriber at gloaming.com
Wed Nov 28 22:28:25 PST 2007
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
More information about the launchd-dev
mailing list