File-FcntlLock

 view release on metacpan or  search on metacpan

lib/File/FcntlLock.pod  view on Meta::CPAN

=head1 DESCRIPTION

File locking in Perl is usually done using the C<flock> function.
Unfortunately, this only allows locks on whole files and is often
implemented in terms of the L<flock(2)> system function which has
some shortcomings (especially concerning locks on remotely mounted
file systems) and slightly different behaviour than L<fcntl(2)>.

Using this module file locking via L<fcntl(2)> can be done (obviously,
this restricts the use of the module to systems that have a L<fcntl(2)>
system call). Before a file (or parts of a file) can be locked, an
object simulating a flock structure, containing information in a
binary format to be passed to L<fcntl(2)> for locking requests, must
be created and its properties set. Afterwards, by calling the L<lock()>
method a lock can be set and removed or it can be determined if and which
process currently holds the lock.

File::FcntlLock (or its alias File::FcntlLock::XS) uses a shared library,
build during installation, to call the L<fcntl(2)> system function directly.
If this is unsuitable there are two alternatives, File::FcntlLock::Pure and
File::FcntlLock::Inline. Both call the Perl C<fcntl> function instead and

lib/File/FcntlLock.pod  view on Meta::CPAN


=item C<l_start()>

Queries or sets the start position (offset) of the lock in the file
according to the mode selected by the L<l_whence> member. See also
the man page for L<lseek(2)>.

=item C<l_len()>

Queries or sets the length of the region (in bytes) in the file to
be locked. A value of 0 is interpreted to mean a lock, starting at
C<l_start>, to the end of the file. E.g., a lock obtained with
L<l_whence> set to C<SEEK_SET> and both L<l_start> and L<l_len> set
to 0 locks the complete file.

According to SUSv3 support for negative values for L<l_len> are
permitted, resulting in a lock ranging from C<l_start+l_len> up to
and including C<l_start-1>. But not all systems support negative
values for L<l_len> and will return an error when you try to obtain
such a lock, so please read the L<fcntl(2)> man page of the system
carefully for details.

lib/File/FcntlLock.pod  view on Meta::CPAN

time. If a signal is received while waiting for the lock the
method returns C<undef> and C<errno> is set to C<EINTR>.

=item C<F_GETLK>

With C<F_GETLK> the L<lock()> method determines if and which process
currently is holding the lock.  If there's no other lock the L<l_type>
property will be set to C<F_UNLCK>. Otherwise the flock structure object
is set to the values that would prevent us from obtaining a lock. There
may be several processes that keep us from getting a lock, including
some that themselves are blocked waiting to obtain a lock. C<F_GETLK>
will only make details of one of these processes visible, and one has
no control over which process this is.

=back

On success the L<lock()> method returns the string "0 but true",
i.e., a value that is true in boolean but 0 in numeric context. If
the method fails (as indicated by an C<undef> return value) you can
either immediately evaluate the error number (using $!, $ERRNO or
$OS_ERROR) or check for it via the methods discussed below at some

lib/File/FcntlLock.pod  view on Meta::CPAN

latest call of L<lock()>. Please take the messages with a grain of
salt, they represent what SUSv3 (IEEE 1003.1-2001) and the Linux,
TRUE64, OpenBSD3 and Solaris8 man pages tell what the error numbers
mean. There could be differences (and additional error numbers) on
other systems. If there was no error the method returns C<undef>.

=item C<system_error()>

While the L<error()> method tries to return a string with some direct
relevance to the locking operation (i.e., "File or segment already
locked by other process(es)" instead of "Permission denied") this method
returns the "normal" system error message associated with C<errno>. The
method returns C<undef> if there was no error.

=back


=head2 EXPORT

The package exports the following constants:

lib/File/FcntlLock/Errors.pm  view on Meta::CPAN



BEGIN {
    # Set up a hash with the error messages, but only for errno's that Errno
    # knows about. The texts represent what is written in SUSv3 and in the
    # man pages for Linux, TRUE64, OpenBSD3 and Solaris8.

    my $err;

    if ( $err = eval { &Errno::EACCES } ) {
        $fcntl_error_texts{ $err } = "File or segment already locked " .
                                     "by other process(es) or file is " .
                                     "mmap()ed to virtual memory";
    }

    if ( $err = eval { &Errno::EAGAIN } ) {
        $fcntl_error_texts{ $err } = "File or segment already locked " .
                                     "by other process(es)";
    }

    if ( $err = eval { &Errno::EBADF } ) {
        $fcntl_error_texts{ $err } = "Not an open file or not opened for " .
                                     "writing (with F_WRLCK) or reading " .
                                     "(with F_RDLCK)";
    }

    if ( $err = eval { &Errno::EDEADLK } ) {
        $fcntl_error_texts{ $err } = "Operation would cause a deadlock";
    }

    if ( $err = eval { &Errno::EFAULT } ) {
        $fcntl_error_texts{ $err } = "Lock outside accessible address space " .
                                     "or to many locked regions";
    }

    if ( $err = eval { &Errno::EINTR } ) {
        $fcntl_error_texts{ $err } = "Operation interrupted by a signal";
    }

    if ( $err = eval { &Errno::ENOLCK } ) {
        $fcntl_error_texts{ $err } = "Too many segment locks open, lock " .
                                     "table full or remote locking protocol " .
                                     "failure (e.g. NFS)";



( run in 0.268 second using v1.01-cache-2.11-cpan-26ccb49234f )