flock#
Place an advisory lock on an open file.
flock is Perl’s portable file-locking primitive. It calls the
underlying flock(2), fcntl(2), or lockf(3) — whichever the
platform provides — on FILEHANDLE and blocks by default until the
requested lock can be granted. Locks cover the whole file, never
a byte range, and are advisory: they coordinate only among
processes that also call flock on the same file. Code that ignores
the lock can still read or modify the contents.
Synopsis#
flock FILEHANDLE, OPERATION
What you get back#
True on success, false on failure (with $! set). Always
check the return value — with LOCK_NB a failure is the normal
“someone else holds it” signal, not an error:
flock($fh, LOCK_EX | LOCK_NB)
or die "already locked: $!";
On a platform that implements none of flock(2), fcntl(2) locking,
or lockf(3), flock raises a fatal error rather than returning
false. On Linux (pperl’s only supported platform) this never happens.
OPERATION values#
OPERATION is one of the mutually exclusive request types, optionally
bitwise-or’ed with the non-blocking flag. Traditional numeric values
are 1, 2, 4, 8 but portable code imports the symbolic names
from Fcntl, either individually or as a group via the
:flock tag:
use Fcntl qw(:flock);
LOCK_SH— shared lock. Multiple processes may hold a shared lock on the same file simultaneously. Used for readers.LOCK_EX— exclusive lock. Only one process may hold it; no other process may hold any lock on the file at the same time. Used for writers.LOCK_UN— release whatever lock this filehandle currently holds.LOCK_NB— bitwise-or withLOCK_SHorLOCK_EXto make the call non-blocking;flockreturns false immediately if the lock cannot be granted, instead of waiting.
An flock call with a new mode atomically replaces an existing lock
on the same filehandle (for example, upgrading LOCK_SH to
LOCK_EX).
Global state it touches#
Sets
$!on failure.Flushes
FILEHANDLE’s output buffer before locking or unlocking, so locked-region data hits the OS before another process can see the lock state change.
Examples#
Exclusive lock for a writer, blocking until granted:
use Fcntl qw(:flock);
open my $fh, ">>", "counter.log" or die $!;
flock($fh, LOCK_EX) or die "lock failed: $!";
print $fh "tick\n";
flock($fh, LOCK_UN) or die "unlock failed: $!";
close $fh;
Non-blocking attempt — skip the work if another process is already running:
use Fcntl qw(:flock);
open my $fh, ">", "/var/run/myjob.lock" or die $!;
flock($fh, LOCK_EX | LOCK_NB)
or do { warn "another instance running\n"; exit 0 };
# ... work ...
# lock auto-released when $fh is closed / program exits
Classic mailbox appender. Note the seek to SEEK_END after
locking — on very old systems >> append mode is not atomic, so the
write position must be re-established once the lock is held:
use Fcntl qw(:flock SEEK_END);
sub lock_mbox { flock($_[0], LOCK_EX) or die "lock: $!" }
sub unlock_mbox { flock($_[0], LOCK_UN) or die "unlock: $!" }
open my $mbox, ">>", "/var/mail/$ENV{USER}" or die $!;
lock_mbox($mbox);
seek($mbox, 0, SEEK_END) or die "seek: $!";
print $mbox $msg, "\n\n";
unlock_mbox($mbox);
close $mbox;
Shared read lock while loading a config file, letting other readers proceed concurrently:
use Fcntl qw(:flock);
open my $fh, "<", "config.dat" or die $!;
flock($fh, LOCK_SH) or die "lock: $!";
my @lines = <$fh>;
close $fh; # releases the lock
Upgrading a shared lock to exclusive — the second flock atomically
swaps modes:
flock($fh, LOCK_SH) or die $!;
# ... inspect contents ...
flock($fh, LOCK_EX) or die $!; # now we intend to write
Edge cases#
Locks are per-filehandle, not per-file. Two independent opens of the same path each have their own lock slot. This is why locking your own file twice from the same process through different handles can deadlock or behave surprisingly on
fcntl(2)-based systems.Closing the filehandle releases the lock. There is no separate “unlock” step required at program exit;
LOCK_UNis useful only when you want to keep the handle open after.LOCK_NBfailure is not a croak. It returns false and sets$!toEWOULDBLOCK. Treat it as an expected outcome, not an error.Advisory only. A process that never calls
flocksees no locks. Useflockas a cooperation protocol among your own programs, not as a security mechanism.Whole files only. There is no byte-range locking through
flock. For record-level locking usefcntlwithF_SETLK/F_SETLKW.NFS and other network filesystems. Some older NFS implementations cannot honour
flockacross hosts; the call may silently become a no-op or return success without providing exclusion. Usefcntllocking if network coordination matters.Fork inheritance. When the platform uses real
flock(2)(Linux does), locks are inherited acrossfork; the child shares them with the parent. Onfcntl(2)-emulated platforms locks do not survive the fork, which makes writing locking servers considerably harder.Buffer flushing. Perl flushes
FILEHANDLE’s output buffer on everyflockcall. Code that mixes bufferedprintwith locking does not need an explicit flush before the lock boundary.Interaction with
dup-style opens. An open of the formopen(my $A, ">>&=", $B)shares the underlying file descriptor with$B, soflock($A)andflock($B)act on the same lock slot. A>>&dup gives each handle its own descriptor and its own lock slot.
Differences from upstream#
Fully compatible with upstream Perl 5.42. pperl runs on Linux only,
where flock(2) is always available, so the “platform has no
locking primitive — fatal error” path documented upstream never
triggers in practice.
See also#
fcntl— byte-range and advisory locking with finer control; use it when whole-file granularity is too coarse or when network filesystems require itopen— produces the filehandleflockoperates on; remember that the required open mode (<vs>) matters forfcntl-emulatedLOCK_SH/LOCK_EXclose— releases anyflockstill held on the handleseek— pair withflockwhen appending to files that other processes may have extended while you waited for the lockfork— lock inheritance across child processes depends on the underlying locking primitiveFcntl— source of theLOCK_SH,LOCK_EX,LOCK_UN,LOCK_NBconstants and the:flockimport tag