Dev-Util
view release on metacpan or search on metacpan
lib/Dev/Util/Sem.pm view on Meta::CPAN
package Dev::Util::Sem;
use Dev::Util::Syntax;
use Dev::Util::File qw(mk_temp_dir dir_writable dir_suffix_slash);
use Exporter qw(import);
use FileHandle;
use Carp();
use Fcntl 'LOCK_EX';
our $VERSION = version->declare("v2.19.42");
our @EXPORT_OK = qw(
new
unlock
);
our %EXPORT_TAGS = ( all => \@EXPORT_OK );
########################################
# Methods #
########################################
sub new {
my $class = shift(@_);
my $filespec = shift(@_) || Carp::croak("What filespec?");
my $timeout = shift || 60;
my $lock_dir_parent = _get_locks_dir($filespec);
local $SIG{ ALRM } = sub { die "Timeout aquiring the lock on $filespec\n" };
alarm $timeout if ( $timeout > 0 );
$filespec =~ s{^.*/}{};
$filespec = $lock_dir_parent . $filespec;
my $fh = FileHandle->new;
$fh->open( '>' . $filespec )
or Carp::croak("Can't open semaphore file $filespec: $!\n");
chmod 0666, $filespec; # assuming you want it a+rw
flock $fh, LOCK_EX;
alarm 0;
return bless { file => $filespec, 'fh' => $fh }, ref($class) || $class;
}
sub unlock {
close( delete $_[0]{ 'fh' } or return 0 );
unlink( $_[0]{ file } );
return 1;
}
sub _get_locks_dir {
my $spec = shift || undef;
my @locks_dirs = qw(/var/lock /var/locks /run/lock /tmp);
my $dirfile_re = qr<^ ( (?: .* / (?: \.\.?\z )? )? ) ([^/]*) >xs;
my ( $spec_dir, $spec_file );
# add spec's dir to list of possible lock dirs
if ( defined $spec && $spec =~ m{/} ) {
( $spec_dir, $spec_file ) = ( $spec =~ $dirfile_re );
unshift @locks_dirs, $spec_dir;
}
# find first writable lock dir
foreach my $locks_dir (@locks_dirs) {
if ( dir_writable($locks_dir) ) {
return dir_suffix_slash($locks_dir);
}
}
Carp::croak("Could not find a writable dir to make lock.$!\n");
}
1;
=pod
=encoding utf-8
=head1 NAME
Dev::Util::Sem - Module to do Semaphore locking
=head1 VERSION
Version v2.19.42
=head1 SYNOPSIS
To ensure that only one instance of a program runs at a time,
create a semaphore lock file. A second instance will wait until
the first lock is unlocked before it can proceed or it times out.
use Dev::Util::Sem;
my $sem = Sem->new('mylock.sem');
...
$sem->unlock;
( run in 1.195 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )