What is the reason for performing a double fork when creating a daemon?
Strictly speaking, the double-fork has nothing to do with re-parenting the daemon as a child of init
. All that is necessary to re-parent the child is that the parent must exit. This can be done with only a single fork. Also, doing a double-fork by itself doesn't re-parent the daemon process to init
; the daemon's parent must exit. In other words, the parent always exits when forking a proper daemon so that the daemon process is re-parented to init
.
So why the double fork? POSIX.1-2008 Section 11.1.3, "The Controlling Terminal", has the answer (emphasis added):
The controlling terminal for a session is allocated by the session leader in an implementation-defined manner. If a session leader has no controlling terminal, and opens a terminal device file that is not already associated with a session without using the
O_NOCTTY
option (seeopen()
), it is implementation-defined whether the terminal becomes the controlling terminal of the session leader. If a process which is not a session leader opens a terminal file, or theO_NOCTTY
option is used onopen()
, then that terminal shall not become the controlling terminal of the calling process.
This tells us that if a daemon process does something like this ...
int fd = open("/dev/console", O_RDWR);
... then the daemon process might acquire /dev/console
as its controlling terminal, depending on whether the daemon process is a session leader, and depending on the system implementation. The program can guarantee that the above call will not acquire a controlling terminal if the program first ensures that it is not a session leader.
Normally, when launching a daemon, setsid
is called (from the child process after calling fork
) to dissociate the daemon from its controlling terminal. However, calling setsid
also means that the calling process will be the session leader of the new session, which leaves open the possibility that the daemon could reacquire a controlling terminal. The double-fork technique ensures that the daemon process is not the session leader, which then guarantees that a call to open
, as in the example above, will not result in the daemon process reacquiring a controlling terminal.
The double-fork technique is a bit paranoid. It may not be necessary if you know that the daemon will never open a terminal device file. Also, on some systems it may not be necessary even if the daemon does open a terminal device file, since that behavior is implementation-defined. However, one thing that is not implementation-defined is that only a session leader can allocate the controlling terminal. If a process isn't a session leader, it can't allocate a controlling terminal. Therefore, if you want to be paranoid and be certain that the daemon process cannot inadvertently acquire a controlling terminal, regardless of any implementation-defined specifics, then the double-fork technique is essential.
I was trying to understand the double fork and stumbled upon this question here. After a lot of research this is what I figured out. Hopefully it will help clarify things better for anyone who has the same question.
In Unix every process belongs to a group which in turn belongs to a session. Here is the hierarchy…
Session (SID) → Process Group (PGID) → Process (PID)
The first process in the process group becomes the process group leader and the first process in the session becomes the session leader. Every session can have one TTY associated with it. Only a session leader can take control of a TTY. For a process to be truly daemonized (ran in the background) we should ensure that the session leader is killed so that there is no possibility of the session ever taking control of the TTY.
I ran Sander Marechal's python example daemon program from this site on my Ubuntu. Here are the results with my comments.
1. `Parent` = PID: 28084, PGID: 28084, SID: 28046
2. `Fork#1` = PID: 28085, PGID: 28084, SID: 28046
3. `Decouple#1`= PID: 28085, PGID: 28085, SID: 28085
4. `Fork#2` = PID: 28086, PGID: 28085, SID: 28085
Note that the process is the session leader after Decouple#1
, because it's PID = SID
. It could still take control of a TTY.
Note that Fork#2
is no longer the session leader PID != SID
. This process can never take control of a TTY. Truly daemonized.
I personally find terminology fork-twice to be confusing. A better idiom might be fork-decouple-fork.
Additional links of interest:
- Unix processes - http://www.win.tue.nl/~aeb/linux/lk/lk-10.html