Filehandles, files, directories

fcntl#

Perform a fcntl(2) file-control operation on a filehandle.

fcntl is the direct Perl binding for the POSIX fcntl(2) system call. It reads or changes per-descriptor state — non-blocking mode, close-on-exec, advisory record locks, descriptor flags — by invoking FUNCTION against FILEHANDLE, with SCALAR acting as either the input argument, the output buffer, or both, depending on which FUNCTION you pass.

The FUNCTION codes are not Perl-level literals; they are C preprocessor macros exposed by the Fcntl module. Load it first, or FUNCTION will be an undefined bareword:

use Fcntl;

Synopsis#

use Fcntl;
fcntl FILEHANDLE, FUNCTION, SCALAR
my $flags = fcntl($fh, F_GETFL, 0);
fcntl($fh, F_SETFL, $flags | O_NONBLOCK);

What you get back#

On success, the integer the kernel returned. When that integer is 0, Perl substitutes the dual-valued string "0 but true" — true in boolean context, numeric 0 in numeric context, and exempt from the Argument "..." isn't numeric warning. This lets you test the result with or die even for operations whose success value is literally zero:

fcntl($fh, F_SETFD, FD_CLOEXEC)
    or die "F_SETFD: $!";

On failure, fcntl returns undef and sets $! to the relevant errno. You do not need to wrap the return in defined — the "0 but true" convention makes a plain truth test sufficient.

For FUNCTION codes that write back through SCALAR (such as F_GETLK), the updated bytes land in the scalar you passed; the return value still follows the rule above.

How SCALAR is used#

SCALAR plays three different roles depending on FUNCTION:

  • Input integer. For flag-setting calls like F_SETFD or F_SETFL, SCALAR is the integer bitmask to install.

  • Ignored placeholder. For flag-getting calls like F_GETFD or F_GETFL, SCALAR is unused by the kernel; pass 0 by convention.

  • In/out struct buffer. For record-locking calls like F_GETLK, F_SETLK, and F_SETLKW, SCALAR must hold a packed struct flock — build it with pack before the call, and for F_GETLK decode the returned bytes with unpack afterward.

When SCALAR is used as an output buffer, pre-size it to at least the length of the struct the kernel will write; an undersized scalar is grown automatically, but pre-sizing makes the intent obvious.

Global state it touches#

  • $! — set on failure to the errno from fcntl(2).

  • Descriptor-level flags on FILEHANDLE (e.g. O_NONBLOCK, FD_CLOEXEC) persist for the lifetime of the descriptor, survive dup and fork according to POSIX rules, and are not Perl-visible through any other variable. The only way to read them back is another fcntl call with F_GETFL / F_GETFD.

Examples#

Make a socket non-blocking — the canonical use:

use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

my $flags = fcntl($remote, F_GETFL, 0)
    or die "F_GETFL: $!";
fcntl($remote, F_SETFL, $flags | O_NONBLOCK)
    or die "F_SETFL: $!";

Set close-on-exec so the descriptor is not inherited by child processes across exec:

use Fcntl qw(F_SETFD FD_CLOEXEC);

fcntl($fh, F_SETFD, FD_CLOEXEC)
    or die "F_SETFD: $!";

Read the current descriptor flags and test a bit:

use Fcntl qw(F_GETFD FD_CLOEXEC);

my $fd_flags = fcntl($fh, F_GETFD, 0);
defined $fd_flags or die "F_GETFD: $!";
if ($fd_flags & FD_CLOEXEC) {
    # descriptor will close on exec
}

Place an advisory write lock on the whole file. The struct flock layout is platform-specific; on Linux s s l l i covers l_type l_whence l_start l_len l_pid:

use Fcntl qw(F_SETLK F_WRLCK SEEK_SET);

my $lock = pack('s s l l i', F_WRLCK, SEEK_SET, 0, 0, 0);
fcntl($fh, F_SETLK, $lock)
    or die "lock refused: $!";

Toggling off a single flag — mask out O_NONBLOCK to return a handle to blocking mode:

use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

my $flags = fcntl($fh, F_GETFL, 0);
fcntl($fh, F_SETFL, $flags & ~O_NONBLOCK)
    or die "F_SETFL: $!";

Edge cases#

  • Forgot use Fcntl: F_GETFL and friends parse as barewords and evaluate to a warning-level nuisance under use strict / use warnings, or to the string "F_GETFL" otherwise — either way the call fails with EINVAL. Always load Fcntl first.

  • "0 but true" return: do not compare the return with == 0 as a failure test. Use a plain boolean (or die) or defined — the former is the idiom.

  • F_SETLK vs F_SETLKW: F_SETLK returns undef and sets $! to EAGAIN / EACCES when another process holds a conflicting lock. F_SETLKW blocks until the lock is granted. Pick deliberately; mixing them up is the usual source of hangs.

  • F_GETLK output: on success the struct flock bytes in SCALAR are overwritten with information about the conflicting lock (or l_type == F_UNLCK if the region is free). unpack back with the same template you packed with.

  • Not every system implements every FUNCTION: fcntl raises an exception on a machine that does not implement fcntl(2) at all. On systems that do, unsupported FUNCTION codes fail with EINVAL via $!. The Fcntl module only exports constants the current platform actually defines.

  • fcntl vs ioctl: both share the argument-processing and return-value convention, but they target different kernel interfaces. Use fcntl for descriptor flags and advisory locks; use ioctl for device-specific control codes.

  • fcntl vs flock: flock uses whole-file BSD-style flock(2) locks, which on Linux interoperate with fcntl POSIX locks only in limited ways. If you need byte-range locking or POSIX semantics (lock released on any close of the file by the owning process), use fcntl with F_SETLK; otherwise flock is simpler.

Differences from upstream#

Fully compatible with upstream Perl 5.42.

See also#

  • Fcntl — the module that exports the F_* / O_* / FD_* / SEEK_* constants fcntl expects; always use it first

  • ioctl — same calling and return-value convention as fcntl, but for device control codes rather than file-control flags

  • flock — simpler whole-file advisory locks; reach for it when you don’t need byte-range or POSIX semantics

  • open — opens the filehandle in the first place; some flags fcntl adjusts (e.g. O_NONBLOCK, O_APPEND) are also settable at open time

  • sysopen — low-level open that takes the same O_* flags from Fcntl; use it when you want the flags applied atomically rather than via a follow-up fcntl(F_SETFL)

  • pack / unpack — required for building and decoding the struct flock buffer used by F_GETLK / F_SETLK