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