How to daemonize a process

Cookbook

use POSIX; sub daemonize { fork and exit; POSIX::setsid(); fork and exit; umask 0; chdir '/'; close STDIN; close STDOUT; close STDERR; }

/dev/null

sub daemonize { fork and exit; POSIX::setsid(); fork and exit; umask 0; chdir '/'; open STDIN , '', '/dev/null'; open STDERR, '>', '/dev/null';

exec

sub daemonize { fork and exit; POSIX::setsid(); fork and exit; umask 0; chdir '/'; exec 'my-daemon'; }

return

exit

sub daemonize { fork and return; POSIX::setsid(); fork and exit; umask 0; chdir '/'; exec 'my-daemon';

use POSIX; sub Fork { my $pid = fork; defined $pid or die "Can't fork: $!

"; $pid } sub daemonize { Fork and return; POSIX::setsid(); Fork and exit; umask 0; chdir '/' or die "Can't chdir to /: $!

"; exec 'my-daemon' die "Can't exec my-daemon: $!

"; }

Analysis

fork (first time)

The first fork allows the child to run the daemon while the parent continues execution, or exits. In addition, it ensures that the child is not a process group leader, so that the following setsid() call will succeed. setsid

This is how we lose our controlling terminal. setsid makes our process the session leader of a new session, and when a new session is created, the session leader has no controlling terminal. fork (second time)

The leader of a new session has no controlling terminal, but it could acquire one, for example, by opening /dev/tty or the like. To ensure that this doesn't happen, we fork again. After the second fork, the child is not the session leader (the parent is the session leader) and only a session leader can acquire a controlling terminal. Of course, the child could become a session leader by executing setsid again, but presumably anyone who does that knows what they are doing. umask 0

umask is inherited across fork and exec , and we don't want our daemon to be limited by whatever umask it happens to inherit from its parent. chdir '/'

The current working directory is inherited across fork and exec . If we leave the daemon running in some random directory, then the file system that contains that directory can never be umount ed, and someone might want to. close

Even though the daemon has no controlling terminal, it may still have open file descriptors on a terminal, and these can cause trouble. For reliable operation, close the system file descriptors.

$^F

Some Perl modules dup STDERR . You can close STDERR , but the dup'd descriptor will remain open on the terminal. One way to avoid this is to close STDERR in a BEGIN block, before the modules load

BEGIN { close STDERR; }

my $fd2 = "/proc/$$/fd/2"; my $stderr = readlink $fd2 or die "Can't readlink $fd2: $!

"; for my $link (</proc/$$/fd/*>) { my($fd) = $link =~ /(\d+)$/; $fd > $^F or next; readlink($link) eq $stderr and POSIX::close($fd); }

Context

setsid()

setsid(2)

setpgid(2)

Here is some context.

Processes and terminals

input (keyboard)

output (screen)

signals (Ctl-C, Ctl-Z, break, etc.)

ls

cat

a daemon should not read input from a keyboard (who is going to be typing at it?)

a daemon should not print output to a screen (who is going to read it?)

a daemon should not receive signals from a terminal

A particular problem is SIGHUP . HUP is short for Hang UP; the terminology dates back to the days when people connected physical terminals to computers using modems and phone lines.

Many programmers will recognize SIGHUP as the signal that you send to a daemon to tell it to re-read its configuration files. However, the original use of SIGHUP was to tell a processes that the phone connection to its terminal had been broken: that it literally no longer had a controlling terminal. The default action for a process that receives SIGHUP is to terminate (see signal(7) ).

The modern equivalent of a physical terminal is a pseudo-terminal, of the sort provided by XTerm or PuTTY. When a pseudo-terminal exits (for example, because the user closes the window on their screen) the OS sends SIGHUP to processes that were controlled by that terminal. (See setpgid(2) for details.) If your daemon still has a controlling terminal, it is liable to exit when this happens. So you want your daemon to not have a controlling terminal.

A daemon that is properly started with no controlling terminal will never receive SIGHUP from the OS. Thus, it is convenient to repurpose SIGHUP to tell the daemon to read its configuration files.

Sessions and process groups

% cat > foo

STDIN

Ctl-D

Ctl-C

cat

If you do

% cat foo | sort | more

STDIN

more

Ctl-C

If you do

% sort foo > bar & % more baz

sort

baz

To manage all this, Unix provides some addition structures for processes

processes are organized into process groups

process groups are organized into sessions

+-session 1 ----------------+ | | | +-process group 1-----+ | | | | | | | process 1 | | | | process 2 | | | | | | | +---------------------+ | | | | +-process group 3-----+ | | | | | | | process 3 | | | | process 4 | | | | process 5 | | | | | | | +---------------------+ | | | +---------------------------+

The shell typically creates a new process group for each pipeline that it runs (even if there is only one process in the pipeline).

Any process in the session can write to the terminal. That is why you sometimes see output from background processes in the middle of something else.

One process group is designated foreground; all other process groups are in background. Processes in the foreground group can read from the terminal; processes in the background will block if they try to read from STDIN . If a signal is generated by the terminal (e.g. Ctl-C ), then that signal is delivered to each process in the foreground process group.

This system allows shells to manage processes in the way that users want, and to make input, output, and signals work the way that users expect.

A process that wants to get out of the system—to not be in the same session as the shell—calls setsid() . It then becomes the session leader of a new session, and that session has no controlling terminal.

Notes