1# Lock Test with graceful termination (SIGTERM or SIGINT) 2 3use strict; 4use warnings; 5 6use Test::More tests => 10; 7use File::NFSLock; 8use Fcntl qw(O_CREAT O_RDWR O_RDONLY O_TRUNC LOCK_EX); 9 10$| = 1; # Buffer must be autoflushed because of fork() below. 11 12my $datafile = "testfile.dat"; 13 14# Wipe lock file in case it exists 15unlink ("$datafile$File::NFSLock::LOCK_EXTENSION"); 16 17# Create a blank file 18sysopen ( my $fh, $datafile, O_CREAT | O_RDWR | O_TRUNC ); 19close ($fh); 20# test 1 21ok (-e $datafile && !-s _); 22 23 24# test 2 25my ($rd1, $wr1); 26ok (pipe($rd1, $wr1)); # Connected pipe for child1 27 28my $pid = fork; 29if (!$pid) { 30 # Child #1 process 31 # Obtain exclusive lock 32 my $lock = new File::NFSLock { 33 file => $datafile, 34 lock_type => LOCK_EX, 35 }; 36 open(STDERR,">/dev/null"); 37 print $wr1 !!$lock; # Send boolean success status down pipe 38 close($wr1); # Signal to parent that the Blocking lock is done 39 close($rd1); 40 if ($lock) { 41 sleep 10; # hold the lock for a moment 42 sysopen(my $fh, $datafile, O_RDWR | O_TRUNC); 43 # And then put a magic word into the file 44 print $fh "exclusive\n"; 45 close $fh; 46 } 47 exit; 48} 49 50# test 3 51ok 1; # Fork successful 52close ($wr1); 53# Waiting for child1 to finish its lock status 54my $child1_lock = <$rd1>; 55close ($rd1); 56# Report status of the child1_lock. 57# It should have been successful 58# test 4 59ok ($child1_lock); 60 61# Pretend like the locked process hit CTRL-C 62# test 5 63ok (kill "INT", $pid); 64 65# Clear the zombie 66# test 6 67ok (wait); 68 69# test 7 70my ($rd2, $wr2); 71ok (pipe($rd2, $wr2)); # Connected pipe for child2 72if (!fork) { 73 # The last lock died, so this should aquire fine. 74 my $lock = new File::NFSLock { 75 file => $datafile, 76 lock_type => LOCK_EX, 77 blocking_timeout => 10, 78 }; 79 if ($lock) { 80 sysopen(my $fh, $datafile, O_RDWR | O_TRUNC); 81 # Immediately put the magic word into the file 82 print $fh "lock2\n"; 83 truncate ($fh, tell $fh); 84 close $fh; 85 } 86 print $wr2 !!$lock; # Send boolean success status down pipe 87 close($wr2); # Signal to parent that the Blocking lock is done 88 close($rd2); 89 exit; # Release this new lock 90} 91# test 8 92ok 1; # Fork successful 93close ($wr2); 94 95# Waiting for child2 to finish its lock status 96my $child2_lock = <$rd2>; 97close ($rd2); 98# Report status of the child2_lock. 99# This should have been successful. 100# test 9 101ok ($child2_lock); 102 103# Load up whatever the file says now 104sysopen(my $fh2, $datafile, O_RDONLY); 105 106$_ = <$fh2>; 107# test 10 108ok /lock2/; 109close $fh2; 110 111# Wipe the temporary file 112unlink $datafile; 113