Starting processes in unix systems (notably linux, but Mac OS and
FreeBSD also follow this) is fairly simple: fork() and immediately
exec() in the child process. If you do anything but call exec() in the
child process you risk deadlocking your program due to multithreading
interactions. Having a program daemonize itself requires doing stuff
other than plain exec() in the child process.
As a result, the classroom "fork, setsid, fork again" algorithm is not
applicable if your program is operating in a multithreaded
environment. Unfortunately, Go pretty much always operates in a
multithreaded environment, because modules can define init() and start
goroutines before your main() executes.
The current state of the art in systems like upstart, systemd (linux)
and launchd (Mac OS), is to write your program without daemonizing
features, and assume that the system management software will start
your process already daemonized.
In other words, don't include daemonization into your program;
instead, when you're ready to deploy it, configure the system
management daemon (sysvinit, upstart, systemd, launchd, windows
services) to start your program with the correct daemonization
procedure.
- Dave
> --
>
>