NAME

Fugu::Daemon - daemonization for Perl programs

SYNOPSIS

use Fugu::Daemon;

Fugu::Daemon->daemonize(
    logfile => '/var/log/mydaemon.log',
    pidfile => '/var/run/mydaemon.pid',
);

DESCRIPTION

Fugu::Daemon turns the program into a daemon, as daemon(3) does. The program forks, and the parent exits. The child becomes a session leader, redirects its standard descriptors away from the terminal, leaves the directory it started in, and sets its file creation mask.

The module keeps no state that a caller can see and has one class method.

daemonize

daemonize(%args) forks into the background and detaches from the controlling terminal.

The parent exits with status 0. Thus daemonize() returns only in the child. The child calls setsid(2) and reopens standard input from /dev/null. The child then appends standard output to logfile and duplicates standard output onto standard error. It changes to the root directory and sets the file creation mask to 022. Last, it takes the PID file when the caller named one.

The child redirects the descriptors before it changes the directory. Thus a relative logfile keeps the meaning that the caller gave it.

These are the arguments:

logfile

The path for standard output and standard error. The default is /dev/null. This default is correct for a daemon that logs through Fugu::Log in syslog mode. The module opens the file in append mode.

pidfile

The PID file the child takes with Fugu::Pidfile. The child acquires it after setsid(2), so the file holds the PID of the session leader. The child holds the lock for the life of the process, even if the caller discards the returned object. The default is no PID file.

RETURN VALUES

daemonize() never returns in the parent. In the child it returns the Fugu::Pidfile object when the caller gave a pidfile, and nothing otherwise.

EXAMPLES

This example daemonizes the program, takes a PID file, and logs through syslog:

my $log = Fugu::Log->new(mode => 'syslog', ident => 'mydaemon');

Fugu::Daemon->daemonize(
    logfile => '/var/log/mydaemon.log',
    pidfile => '/var/run/mydaemon.pid',
);

$log->info('started, pid %d', $$);

ERRORS

daemonize() dies and does not return if the fork fails, if setsid(2) fails, if the module cannot redirect one of the three standard descriptors, if it cannot change to the root directory, or if it cannot take the PID file. A daemon cannot recover from these startup conditions.

A failure to take the PID file most often means that a second daemon already holds it.

SEE ALSO

setsid(2), umask(2), daemon(3), Fugu::Log, Fugu::Pidfile, Fugu::Privdrop, Fugu::Process

AUTHORS

Dick Olsson <hi@senzilla.io>

CAVEATS

Call daemonize() before you open files or sockets that the daemon must keep. The child redirects the standard descriptors, but it inherits everything that is already open with no change.

The daemon never removes the PID file. An unlink(2) in a root-owned directory needs a write permission on the directory that a daemon gives up at the privilege drop. The is_stale() method of Fugu::Pidfile covers the leftover file.