NAME

Fugu::Pidfile - locked PID file

SYNOPSIS

use Fugu::Pidfile;

my $pidfile = Fugu::Pidfile->new(path => '/var/run/mydaemon.pid');

if (my $pid = $pidfile->is_running) {
    die "already running as pid $pid\n";
}

$pidfile->acquire;

DESCRIPTION

Fugu::Pidfile manages one PID file. It also reports if the process that the file names still runs. The module exists so that a daemon, its rc.d(8) script, and a control utility can all agree on the same question.

Every write takes the lock before it truncates. Thus a concurrent reader never sees an empty file.

new

new(%args) creates an object for the named file. The method does not create and does not read the file at this point.

This is the argument:

path

The PID file. This argument is necessary.

path

path() returns the file that the object manages.

write_pid

write_pid($pid) writes $pid and a newline to the PID file, then releases the lock. The default for $pid is the process ID of the caller.

acquire

acquire($pid) writes the PID and keeps the locked handle open. The lock lives until the object is destroyed, or until the process exits. While one process holds the lock, an acquire() from a second process fails at once and does not wait. Thus "am I already running" has an authoritative answer that no read_pid() race can spoil.

read_pid

read_pid() returns the process ID that the file holds. The first line must be a sequence of decimal digits. If the contents are different, or if the file is absent, the method returns no PID.

remove

remove() removes the PID file.

is_running

is_running() returns the process ID from the file if that process is alive. The method uses Fugu::Process for the liveness check.

is_stale

is_stale() reports if the PID file names a process that is not alive now. In this condition, a daemon can take the file and does not refuse to start.

error

error() returns the most recent failure as a message that a log can carry.

RETURN VALUES

new() returns an object.

write_pid(), acquire() and remove() return 1 on success. They return undef on failure and put the reason in error().

read_pid() and is_running() return a process ID, or undef when there is no process ID to report.

is_stale() returns 0 when the file holds no readable PID. Thus an absent PID file is not stale.

EXAMPLES

This example prevents a second start and holds the file for the life of the daemon:

my $pidfile = Fugu::Pidfile->new(path => '/var/run/mydaemon.pid');

if (my $pid = $pidfile->is_running) {
    die "mydaemon already running as pid $pid\n";
}

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

ERRORS

new() dies when path is absent or empty. That is a programming error.

No other method dies. They report a failure to open, lock, write or unlink the file through the return value and error().

SEE ALSO

flock(2), unlink(2), Fugu::Daemon, Fugu::Process

AUTHORS

Dick Olsson <hi@senzilla.io>

CAVEATS

write_pid() releases its lock when it closes the file, at the end of the call. The lock puts two concurrent writes in sequence. It does not hold the PID file for the life of the daemon. Use acquire() for that. read_pid() does not take a lock.

A check with is_running() and then an action on the answer is a race condition. In between, the process can exit, or a different process can claim the file. acquire() has no such window.

is_running() has the same limits as the liveness check of Fugu::Process. That check cannot show the difference between the initial process and a later process with the same ID.