in reply to Re: Frustration with changing lock type
in thread Frustration with changing lock type
Thanks for the reply Hugo. I went with something like what you suggest. Added a test before we try to aquire the LOCK_EX to make sure the lockfile doesnt exist or is at least 3 seconds old, and double checking that the process data stays the same after the LOCK_UN and LOCK_SH. The append logic I didnt quite follow so I didnt go that way. Here is what I have:
sub get_lock { my ($lock_dir,$name)=@_; my $debug=1; $name=~s/[^-\w.#!\@~=+%\$]//g; my $lockfile=catfile($lock_dir,$name.'.lock'); print "Trying lockfile $lockfile\n"; if (-e $lockfile and (time()- -M $lockfile)<3) { print "\tLockfile exists and is very recent skipping for now\n +"; return; } sysopen(my $FH, $lockfile, O_RDWR | O_CREAT) or do { warn "can't open $lockfile: $!" if $debug; return; }; # autoflush $FH select( (select($FH), $|++)[0] ); my ( $time, $process, $lname ); if (flock( $FH, LOCK_EX | LOCK_NB )) { ( $time, $process, $lname )=split /\|/,join "",<$FH>; seek $FH, 0, 0 or die "Failed rewind:$!"; if ($debug) { if ($process) { print "\tLockfile appears to be abandonded by Process +#$process started at $time\n" } else { print "\tLockfile appears to be unprocessed\n" } } my $lock_msg=join("|", iso_time(), $$, $name)."\n"; print $FH $lock_msg; truncate($FH, tell($FH)) or die "Failed to truncate:$!"; flock($FH, LOCK_UN) or die "sharedlock: $!"; flock($FH, LOCK_SH|LOCK_NB) or do { print "\tFailed to relock!\n" if $debug; return; }; seek $FH, 0, 0 or die "Failed rewind2:$!"; my $msg=<$FH>; unless ($msg eq $lock_msg) { print "\tWhoops, (harmless) race condition on $lockfile!\n +"; return } print "File Locked! : $lock_msg"; return OnDestroy { print "*** Finished with and removing $loc +kfile ***\n"; close $FH or die "Failed to close \$FH:$!" +; unlink $lockfile or die "Failed to unlink +$lockfile\n"; undef $FH; }; } elsif (flock($FH, LOCK_SH)) { ( $time, $process, $lname )=split /\|/,join "",<$FH>; print "\tLockfile appears to be locked by Process #$process at + $time\n" if $debug; } else { print "\tFailed to get lock! Not sure why.\n"; } return }
Yes its a bit wordy, id be interested to see a less clunky implementation if anyone feels inclined.
Incidentally there is no need to wait to get the exclusive lock. Under normal situations this will be polling a table in a DB every 60 seconds or so, and then processing any records it finds there. So if the lock file is too young returning to try the next record is better.
Cheers
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Re: Re: Frustration with changing lock type
by hv (Prior) on Apr 14, 2004 at 12:47 UTC | |
by tye (Sage) on Apr 14, 2004 at 15:11 UTC | |
by demerphq (Chancellor) on Apr 14, 2004 at 12:53 UTC | |
by hv (Prior) on Apr 14, 2004 at 13:02 UTC |