What is the reason for performing a double fork when creating a daemon?
Asked Answered
L

9

210

I'm trying to create a daemon in python. I've found the following question, which has some good resources in it which I am currently following, but I'm curious as to why a double fork is necessary. I've scratched around google and found plenty of resources declaring that one is necessary, but not why.

Some mention that it is to prevent the daemon from acquiring a controlling terminal. How would it do this without the second fork? What are the repercussions?

Lighting answered 19/5, 2009 at 7:25 Comment(4)
https://mcmap.net/q/25665/-why-fork-twice-duplicate/…Strauss
One difficulty with doing a double fork is that the parent can't easily get the PID of the grandchild process (the fork() call returns the child's PID to the parent, so it's easy to get the PID of the child process, but not so easy to get the PID of the grandchild process).Noami
@CraigMcQueen I am in need of knowing the grandchild processes PID. What is the way to do this?Hollander
@Hollander using some sort of IPC (inter-process communication). Before the fork, you could create a pipe, then the child could send the grandchild's PID through the pipe back to the parent.Noami
H
123

Looking at the code referenced in the question, the justification is:

Fork a second child and exit immediately to prevent zombies. This causes the second child process to be orphaned, making the init process responsible for its cleanup. And, since the first child is a session leader without a controlling terminal, it's possible for it to acquire one by opening a terminal in the future (System V- based systems). This second fork guarantees that the child is no longer a session leader, preventing the daemon from ever acquiring a controlling terminal.

So it is to ensure that the daemon is re-parented onto init (just in case the process kicking off the daemon is long lived), and removes any chance of the daemon reacquiring a controlling tty. So if neither of these cases apply, then one fork should be sufficient. "Unix Network Programming - Stevens" has a good section on this.

Hindman answered 19/5, 2009 at 7:42 Comment(5)
This is not entirely correct. The standard way to create a daemon is to simply do p=fork(); if(p) exit(); setsid(). In this case, the parent also exits and the first child process is reparented. The double-fork magic is only required to prevent the daemon from acquiring a tty.Synod
So, as I understand it, if my program starts and forks a child process, this very first child process will be a session leader and will be able to open a TTY terminal. But if I fork again from this child and terminate this first child, the second forked child won't be a session leader and won't be able to open a TTY terminal. Is this statement correct?Kancler
@tonix: simply forking does not create a session leader. That is done by setsid(). So, the first forked process becomes a session leader after calling setsid() and then we fork again so that the final, double-forked process is no longer a session leader. Other than the requirement of setsid() to be a session leader, you are spot on.Hassan
@Synod Is there anyway to prevent the daemon from acquiring a tty without forking twice? Why would double forking prevent it from acquiring one if a single fork doesn't?Throaty
The session leader is a controlling process connecting to the tty. If you want to prevent a process from acquiring a tty, the process shouldn't be the session leader. So, i think the only way to do that is through double-forking.Semiweekly
S
206

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:

Siliqua answered 22/3, 2011 at 4:19 Comment(6)
Forking twice also prevents creating zombies when parent process runs for longer time and for some reason removing default handler for signal informing that process died.Cleodal
But second for can also call decouple and become session leader and then acquire terminal.Cleodal
This is not true. The first fork() already prevents creating zombies, provided you close the parent.Synod
A minimal example to produce the above quoted results: gist.github.com/cannium/7aa58f13c834920bb32cJermayne
Would it be any good to call setsid() before a single fork()? Actually I guess the answers of this question answer that.Noami
For anyone like me wondering what TTY is: this blog post is a good one to study.Convection
C
155

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 (see open()), 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 the O_NOCTTY option is used on open(), 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.

Corenda answered 1/5, 2013 at 11:54 Comment(8)
+1 Too bad this answer came ~four years after the question was asked.Nugatory
But that still doesn't explain why it's so terribly important that a daemon can't reacquire a controlling terminalCooperation
The keyword is "inadvertently" acquire a controlling terminal. If the process happens to open a terminal, and it becomes the processes controlling terminal, than if somebody issues a ^C from that terminal it could terminate the process. So it might be nice to protect a process from having that happen to it inadvertently. Personally I'll stick to a single fork and setsid() for code I write that I know won't be opening terminals.Fudge
@BobDoolittle: One thing to note, however, is that opening a terminal device file is but one way that a process could reacquire a controlling terminal. "The controlling terminal for a session is allocated by the session leader in an implementation-defined manner." That means implementations could provide other ways that a session leader can acquire a controlling terminal. I'm not always paranoid, but when I am, I daemonize my processes carefully :)Corenda
@Fudge how could this happen "inadvertently"? A process won't just willy nilly end up opening terminals if it's not written to do so. Maybe double-forking is useful if you the programmer don't know the code and don't know if it might open a tty.Treadmill
@Treadmill Imagine what might happen if you add a line like this to your daemon's configuration file: LogFile=/dev/console. Programs don't always have compile-time control over which files they might open ;)Corenda
@Treadmill yes you always need to vet your inputs. If you have a config file that controls what you are opening, this can be significant. This is a case of you the programmer not knowing what it might open. But if the files you open are not specified via user/admin input, this is just sloppy programming. It reminds me of the days people used to type "sync" twice before shutting down a system. In fact the only purpose the second sync served was a delay so the first async flush to disk could have time to complete.Fudge
FWIW, you're right double-fork isn't needed to reparent to init when demonizing, but that part is needed when a demon wants to fork and reparent a child and keep running: https://mcmap.net/q/25665/-why-fork-twice-duplicate/53974 (of course, in that scenario you can avoid reparenting and do your own reaping but it can be complicated).Gosling
H
123

Looking at the code referenced in the question, the justification is:

Fork a second child and exit immediately to prevent zombies. This causes the second child process to be orphaned, making the init process responsible for its cleanup. And, since the first child is a session leader without a controlling terminal, it's possible for it to acquire one by opening a terminal in the future (System V- based systems). This second fork guarantees that the child is no longer a session leader, preventing the daemon from ever acquiring a controlling terminal.

So it is to ensure that the daemon is re-parented onto init (just in case the process kicking off the daemon is long lived), and removes any chance of the daemon reacquiring a controlling tty. So if neither of these cases apply, then one fork should be sufficient. "Unix Network Programming - Stevens" has a good section on this.

Hindman answered 19/5, 2009 at 7:42 Comment(5)
This is not entirely correct. The standard way to create a daemon is to simply do p=fork(); if(p) exit(); setsid(). In this case, the parent also exits and the first child process is reparented. The double-fork magic is only required to prevent the daemon from acquiring a tty.Synod
So, as I understand it, if my program starts and forks a child process, this very first child process will be a session leader and will be able to open a TTY terminal. But if I fork again from this child and terminate this first child, the second forked child won't be a session leader and won't be able to open a TTY terminal. Is this statement correct?Kancler
@tonix: simply forking does not create a session leader. That is done by setsid(). So, the first forked process becomes a session leader after calling setsid() and then we fork again so that the final, double-forked process is no longer a session leader. Other than the requirement of setsid() to be a session leader, you are spot on.Hassan
@Synod Is there anyway to prevent the daemon from acquiring a tty without forking twice? Why would double forking prevent it from acquiring one if a single fork doesn't?Throaty
The session leader is a controlling process connecting to the tty. If you want to prevent a process from acquiring a tty, the process shouldn't be the session leader. So, i think the only way to do that is through double-forking.Semiweekly
H
11

Taken from Bad CTK:

"On some flavors of Unix, you are forced to do a double-fork on startup, in order to go into daemon mode. This is because single forking isn’t guaranteed to detach from the controlling terminal."

Hijoung answered 19/5, 2009 at 7:32 Comment(6)
How can single fork not detach from the controlling terminal but double fork do so? What unixes does this occur on?Catha
A daemon must close it's input and output file descriptors (fds), otherwise, it would be still attached to the terminal it was started in. A forked process inherits those from the parent. Apparently, the first child closes the fds but that doesn't clean up everything. On the second fork, the fds don't exist, so the second child can't be connected to anything anymore.Celsacelsius
@Aaron: No, a daemon properly "detaches" itself from its controlling terminal by calling setsid after an initial fork. It then ensures that it stays detached from a controlling terminal by forking again and having the session leader (the process that called setsid) exit.Corenda
@bdonlan: It's not fork that detaches from the controlling terminal. It's setsid that does it. But setsid will fail if it is called from a process group leader. So an initial fork must be done before setsid to ensure that setsid is called from a process that is not a process group leader. The second fork ensures that the final process (the one that will be the daemon) is not a session leader. Only session leaders can acquire a controlling terminal, so this second fork guarantees that the daemon won't inadvertently reacquire a controlling terminal. This is true of any POSIX OS.Corenda
@DanMoulding This does not guarante that second child won't acquire controlling terminal because it can call setsid and become session leader and then acquire control terminal.Cleodal
This answer is poor, but ends up being good because of the comment from @CathaAllix
N
7

According to "Advanced Programming in the Unix Environment", by Stephens and Rago, the second fork is more a recommendation, and it is done to guarantee that the daemon does not acquire a controlling terminal on System V-based systems.

Nullification answered 19/5, 2009 at 7:33 Comment(0)
P
3

One reason is that the parent process can immediately wait_pid() for the child, and then forget about it. When then grand-child dies, it's parent is init, and it will wait() for it - and taking it out of the zombie state.

The result is that the parent process doesn't need to be aware of the forked children, and it also makes it possible to fork long running processes from libs etc.

Philadelphia answered 19/5, 2009 at 7:43 Comment(0)
C
3

It might be easier to understand in this way:

  • The first fork and setsid will create a new session (but the process ID == session ID).
  • The second fork makes sure the process ID != session ID.
Commonalty answered 28/8, 2018 at 3:15 Comment(0)
C
2

The daemon() call has the parent call _exit() if it succeeds. The original motivation may have been to allow the parent to do some extra work while the child is daemonizing.

It may also be based on a mistaken belief that it's necessary in order to ensure the daemon has no parent process and is reparented to init - but this will happen anyway once the parent dies in the single fork case.

So I suppose it all just boils down to tradition in the end - a single fork is sufficient as long as the parent dies in short order anyway.

Catha answered 19/5, 2009 at 7:33 Comment(0)
B
2

A decent discussion of it appear to be at http://www.developerweb.net/forum/showthread.php?t=3025

Quoting mlampkin from there:

...think of the setsid( ) call as the "new" way to do thing (disassociate from the terminal) and the [second] fork( ) call after it as redundancy to deal with the SVr4...

Bluetongue answered 19/5, 2009 at 7:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.