For years we've had a process-monitoring/control script as part of our application. The default behavior of the script is to daemonize itself. Often the script is launched, of necessity, by non-privileged users. For reasons I'll not elaborate, we need to keep both the script and this behavior.
On OSX systems, we have traditionally had the script restart itself in the background via the /usr/libexec/StartupItemContext launch script provided by Apple. This puts our process in the Mach StartupItem bootstrap context rather than the login bootstrap context. This is necessary because without that context switch, if and when the user logs out, which is also often necessary, the script loses access to directory services, getpwuid(), DNS services, etc. The original internal lines that daemonized the script looked essentially like this (in perl):
my $cmd = "/usr/libexec/StartupItemContext myscript @Commandline > logs/startup 2>&1" ;
system( "$cmd &") ;
exit 0 ;
When OSX Yosemite came out, that StartupItemContext script disappeared, so we switched to direct invocation of launchctl:
my $cmd = "/usr/launchctl bsexec / myscript @Commandline > logs/startup 2>&1" ;
system( "$cmd &") ;
exit 0 ;
With the recent OSX 10.10.3 upgrade, however, the bsexec subcommand of launchctl suddenly requires root privileges:
% launchctl bsexec
This subcommand requires root privileges: bsexec
%
This creates for us the showstopper problem that non-privileged users can no longer get our monitoring/control script to daemonize itself.
It seems that Glassfish has encountered this problem and addressed it with a patch that replaces
/bin/launchctl bsexec /
with
nohup
This may work for the Glassfish implementation, however I don't think for us. Notwithstanding the fact that I don't understand it -- i.e. why a simple blocking of SIGHUP would prevent a process in decommissioned login bootstrap context from losing services -- it also doesn't seem to work in our tests for all system services we need.
What is the new, canonical way to daemonize a process on OSX starting from a non-privileged, Mach "login" bootstrap context, without losing access to critical system services like DNS etc. when the user logs out?
"from a non-privileged, Mach "login" bootstrap context" unfortunately is very unlikely to have a "canonical way." The only canonical way is to launch services on demand via launchd. Even "bsexec" is barely supported and hardly documented. In my experience, it isn't possible to keep up with OS X changes and never redesign your launch systems. I redesign the daemon system about every other release because Apple breaks it, and they're going to keep breaking it. The only answer is to keep trying to make your requirements simpler. But pretty much any process that wants to run all the time, rather than on demand, is in direct violation of Apple's stated intent, so it's going to tend to break.
The solution given by Apple is to create a LaunchDaemon and assign it a UserName
in your launchd plist. You must start privileged, and then switch to the user (and it needs to be a fixed user, not "the logged in user" since that would be a LaunchAgent). You can't upgrade your access this way. You must not daemonize yourself (again, the canonical answer is: don't do that. See the launchd.plist man page.)
I suspect the Glassfish nohup
solution is just a dodge that doesn't actually put them in the Mach context. They're just trying to avoid being killed when the parent shell exits. That probably won't help you.
In my experience, the most robust solutions are multi-part. You wind up with one piece that is run as a system LaunchDaemon (with KeepAlive), and another piece that is a user LaunchAgent, and you let them communicate over IPC so that you can access the context you need for each activity you need to do. Yes, this is typically much more complicated to implement. Simpler solutions tend not to work.
And of course you have to constantly ask yourself "is there any way I could achieve this by doing things the way Apple wants me to." That means XPC is strongly preferred, followed by on-demand LaunchDaemons and LaunchAgents. If you build your system to use XPC components, you'll likely survive more OS X upgrades. Any work around you figure out that doesn't use these pieces will probably have to be fixed again in 10.11.