[Linux] daemon() considered harmful
I’m currently writing a Linux program that is supposed to run in the background. When it was time to implement the
--daemonize, I look at the current options and I was quite surprised to learn that
fork() are not the best way to write a daemon nowadays.
Indeed, the current state of the industry is to let the init system (
upstart…) do the daemonization. Forking the process make the work of the init system harder, and therefore is now considered an anti-pattern.
See below some references.
For developing a new-style daemon, none of the initialization steps recommended for SysV daemons need to be implemented. New-style init systems such as systemd make all of them redundant. Moreover, since some of these steps interfere with process monitoring, file descriptor passing and other functionality of the init system, it is recommended not to execute them when run as new-style service.
If the process is started by a super-server daemon, such as inetd, launchd, or systemd, the super-server daemon will perform those functions for the process (except for old-style daemons not converted to run under systemd and specified as Type=forking and “multi-threaded” datagram servers under inetd).
d├ªmon supervisors assume (quite reasonably) that if their child process exits then the d├ªmon has died and can be restarted. (Conversely, they quite reasonably assume that they can do things like stop the d├ªmon cleanly by sending their child process a SIGTERM signal.) The old BSD and System 5 init programs do this. So, too, do most proper d├ªmon supervision toolkits from the past 30 years. Forking to “put the d├ªmon into the background” entirely defeats such tools; but it is ironic that it does so to no good end, because, even without fork()ing, d├ªmons invoked by such supervisors are already “in the background”. The d├ªmon supervisors are already running asynchronously from interactive shells, without controlling terminals, and without any interactive shells as their session leader.
I’d even go one step further and say that you shouldn’t bother with a non-foreground mode. All modern init systems and process managers support non-forking processes (i.e. ones that stay in the foreground); and, in fact, a few have limited or no support for processes that do fork. Why, then, does it make sense to include your own implementation of that functionality? There are lots of subtle details that are easy to get wrong if you try to roll your own, and there’s no practical benefit to having it built in.