From: Eric Gillespie Date: Fri, 5 Dec 2014 03:05:30 +0000 (-0800) Subject: implement lkopen_fcntl from nmh X-Git-Url: https://diplodocus.org/git/minc/commitdiff_plain/6c64153438d8b0c55e987f794473da1d64951be2 implement lkopen_fcntl from nmh --- diff --git a/minc b/minc index 224e56a..db8cdff 100755 --- a/minc +++ b/minc @@ -39,13 +39,16 @@ $SIG{'PIPE'} = 'IGNORE'; use Data::Dumper; use Errno; -use Fcntl qw(O_WRONLY O_EXCL O_CREAT); +use Fcntl; use FileHandle; +use File::FcntlLock; use File::Temp qw(tempfile); use File::stat; use Getopt::Long qw(:config gnu_getopt no_ignore_case); use Pod::Usage; +use constant LOCK_TRIES => 60; + our $VERSION = 1; # If a filter set's header is $MAGIC_TO_TOKEN, that set is compared @@ -362,6 +365,44 @@ sub mark { close($fh) or die("close(>$fn): $!"); } +# Based on nmh's lkopen_fcntl +# Return 0 for success, errno on failure. +sub lkopen_fcntl { + my $file = shift; + my $access = shift; + my $mode = shift; + my $errno = 0; + + # The assumption here is that if you open the file for writing, you + # need an exclusive lock. + + my $tries = LOCK_TRIES; + for (;;) { + sysopen(my $fh, $file, $access, $mode) or die("sysopen($file): $!"); + + my $flk = File::FcntlLock->new; + $flk->l_start(0); + $flk->l_len(0); + $flk->l_type(($access & O_ACCMODE) == O_RDONLY ? F_RDLCK : F_WRLCK); + $flk->l_whence(SEEK_SET); + + # Really should only retry on EAGAIN and EINTR... + if ($flk->lock($fh, F_SETLK)) { + return $fh, undef; + } + + $errno = $flk->lock_errno; + close($fh) or die("close($file): $!"); + + if (--$tries == 0) { + last; + } + sleep(1); + } + + return undef, $errno; +} + sub store_message { my $msg = shift; my $mhfolder = shift;