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.