Fugu

Fugu::Pidfile(3p) Perl Library Manual Fugu::Pidfile(3p)

Fugu::Pidfile - locked PID file

    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;

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(%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() returns the file that the object manages.

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($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() 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() removes the PID file.

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() 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() returns the most recent failure as a message that a log can carry.

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.

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',
    );

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().

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

Dick Olsson <hi@senzilla.io>

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.

2026-10-16 OpenBSD