I found the following function in the source code of catwm (a minimalistic window manager):
void spawn(const Arg arg) {
if(fork() == 0) {
if(fork() == 0) {
if(dis)
close(ConnectionNumber(dis));
setsid();
execvp((char*)arg.com[0],(char**)arg.com);
}
exit(0);
}
}
I don't understand why not simply
void spawn(const Arg arg) {
if(fork() == 0) {
if(dis)
close(ConnectionNumber(dis));
setsid();
execvp((char*)arg.com[0],(char**)arg.com);
}
}
?
Are there any benefits of using the double fork()
here?
The following paragraphs, quoted from Stevens and Rago Advanced Programming in the UNIX Environment, describe two of six coding rules for writing a daemon. Specifically, they implement them in a single daemonize
function listed in Figure 13.1 in case you want to look it up.
- Call fork and have the parent exit. This does several things. First, if the daemon was started as a simple shell command, having the parent terminate makes the shell think that the command is done. Second, the child inherits the process group ID of the parent but gets a new process ID, so were guaranteed that the child is not a process group leader. This is a prerequisite for the call to setsid that is done next.
- Call setsid to create a new session. The three steps listed in Section 9.5 occur. The process (a) becomes the leader of a new session, (b) becomes the leader of a new process group, and (c) is disassociated from its controlling terminal.
- Under System Vbased systems, some people recommend calling fork again at this point, terminating the parent, and continuing the daemon in the child. This guarantees that the daemon is not a session leader, which prevents it from acquiring a controlling terminal under the System V rules (Section 9.6). Alternatively, to avoid acquiring a controlling terminal, be sure to specify O_NOCTTY whenever opening a terminal device.
In your changed code, the parent doesn't exit()
which will continue its execution after spawn()
is called; the exact behavior would depend on what follows the spawn()
call.
credentials(7)
man page for information about controlling terminals: All of the processes in a session share a controlling terminal. The controlling terminal is established when the session leader first opens a terminal (unless the O_NOCTTY flag is specified when calling open(2)). A terminal may be the controlling terminal of at most one session. So it holds for Linux. — Aug 28, 2022 at 20:29 External links referenced by this document: