I’m working on implementing a self-updater for a daemon on OS X. The update is published as a .pkg file, so what I’m trying to do is as follows:
When the daemon is notified that an update is available, it calls installer via the system() call to install the package. The package contains a newer version of the daemon, a preupgrade script that stops the daemon (launchctl unload /Library/LaunchDaemons/foo.plist), and a postflight script that starts it back up after the new version is installed. The problem I’m having is that the installer process is quitting prematurely. I suspect that it may be because the installer kills its parent process in order to update it, and then gets killed itself instead of continuing as its own orphan process. I’ve tried the following with no luck:
- Postpending the installer command with ‘&’ to run it in the
background - Wrapping the installer command with nohup
The install command completes consistently without error when I run it from the command line, and fails consistently when run from the installer. When called from the installer, I’m piping the output to a file, and sometimes it has nothing, and sometimes it shows the install getting to about 41% completion before output stops. Any ideas on how I can figure out what’s happening to the process or make sure it stays alive without its parent?
When you call
launchctl unload, it kills the entire process group (unlike a simplekill). You want to move your subprocess into a separate process group. The easiest way is with the C callsetsid().If you’re in the middle of a shell script, you should look at the following approaches. I haven’t tried these since I was dealing with a C program and could
setsid():set -m. This is supposed to turn on monitor mode, which says “Background processes run in a separate process group and a line containing their exit status is printed upon their completion.”