File Coverage

blib/lib/Dir/Flock.pm
Criterion Covered Total %
statement 159 241 65.9
branch 43 112 38.3
condition 17 41 41.4
subroutine 26 34 76.4
pod 12 12 100.0
total 257 440 58.4


line stmt bran cond sub pod time code
1             package Dir::Flock;
2 14     14   915240 use strict;
  14         140  
  14         415  
3 14     14   76 use warnings;
  14         31  
  14         352  
4 14     14   84 use Carp;
  14         87  
  14         939  
5 14     14   8181 use Time::HiRes;
  14         21087  
  14         55  
6 14     14   12566 use File::Temp;
  14         307291  
  14         1050  
7 14     14   114 use Fcntl ':flock';
  14         31  
  14         1649  
8 14     14   9011 use Data::Dumper; # when debugging is on
  14         99382  
  14         929  
9 14     14   106 use base 'Exporter';
  14         30  
  14         4572  
10              
11             our $VERSION = '0.09';
12             my %TMPFILE;
13             my %LOCK;
14             our @EXPORT_OK = qw(getDir lock lock_ex lock_sh unlock lockobj lockobj_ex
15             lockobj_sh sync sync_ex sync_sh);
16             our %EXPORT_TAGS = ('all' => \@EXPORT_OK);
17             our $errstr;
18              
19             # configuration that may be updated by user
20             our $LOCKFILE_STUB = "dir-flock-";
21             our $PAUSE_LENGTH = 0.001; # seconds
22             our $CHECK_DELAY = 0.001; # seconds
23             our $HEARTBEAT_CHECK = 30; # seconds
24             our $_DEBUG = $ENV{DEBUG} || $ENV{DIR_FLOCK_DEBUG} || 0;
25              
26             sub getDir {
27 10     10 1 20004514 my ($rootdir,$persist,$template) = @_;
28 10 50 33     726 if (-f $rootdir && ! -d $rootdir) {
29 0         0 require Cwd;
30 0         0 require File::Basename;
31 0         0 $rootdir = File::Basename::dirname(Cwd::abs_path($rootdir));
32             }
33 10   50     152 $template //= "dflock-XXXX";
34 14     14   107 no warnings 'redefine';
  14         42  
  14         38312  
35 10     0   262 local *File::Temp::_replace_xx = sub { $_[0] };
  0         0  
36 10         144 my $tmpdir = File::Temp::tempdir(
37             TEMPLATE => $template, DIR => $rootdir, CLEANUP => !$persist );
38 10         9294 $tmpdir;
39             }
40              
41             ### core functions
42              
43 8     8 1 348314 sub lock { goto &lock_ex }
44              
45             sub lock_ex {
46 15     15 1 4962 my ($dir, $timeout) = @_;
47 15         213 $errstr = "";
48 15 50       284 return if !_validate_dir($dir);
49 15   33     151 my $P = $_DEBUG && _pid();
50 15         148 my ($filename,$now) = _create_lockfile( $dir, "excl" );
51 15         80 my $last_check = $now;
52 15   100     267 my $expire = $now + ($timeout || 0);
53 15         65 $TMPFILE{ $filename } = _pid();
54 15         141 while (_oldest_file($dir) ne $filename) {
55 8929         456481 unlink $filename;
56 8929         55240 delete $TMPFILE{$filename};
57 8929 50       26242 $P && print STDERR "$P $filename not the oldest file...\n";
58 8929 100 100     30948 if (defined($timeout) && Time::HiRes::time > $expire) {
59 5         37 $errstr = "timeout waiting for exclusive lock for '$dir'";
60 5 50       18 $P && print STDERR "$P timeout waiting for lock\n";
61 5         47 return;
62             }
63 8924         18975110 Time::HiRes::sleep $PAUSE_LENGTH * (1 + 2 * rand());
64 8924 100       103875 if (Time::HiRes::time > $last_check + $HEARTBEAT_CHECK) {
65 1 50       20 $P && print STDERR "$P check heartbeat of lock holder\n";
66 1         30 _ping_oldest_file($dir);
67 1         8 $last_check = Time::HiRes::time;
68             }
69 8924         31990 ($filename,$now) = _create_lockfile( $dir, "excl" );
70 8924         29108 $TMPFILE{ $filename } = _pid();
71             }
72 10 50       69 $P && print STDERR "$P lock successful to $filename\n";
73 10         81 $LOCK{$dir}{_pid()} = $filename;
74 10         79 1;
75             }
76              
77             sub lock_sh {
78 4     4 1 22100 my ($dir, $timeout) = @_;
79 4         70 $errstr = "";
80 4 50       90 return if !_validate_dir($dir);
81 4   33     45 my $P = $_DEBUG && _pid();
82 4         59 my ($filename,$now) = _create_lockfile( $dir, "shared" );
83 4         17 my $last_check = $now;
84 4   50     79 my $expire = $now + ($timeout || 0);
85 4         21 $TMPFILE{ $filename } = _pid();
86 4         60 while (_oldest_file($dir) =~ /_excl_/) {
87 2752         116048 unlink $filename;
88 2752         15014 delete $TMPFILE{$filename};
89 2752 50       6251 $P && print STDERR "$P $filename not the oldest file...\n";
90 2752 100 66     7063 if (defined($timeout) && Time::HiRes::time > $expire) {
91 1         5 $errstr = "timeout waiting for exclusive lock for '$dir'";
92 1 50       3 $P && print STDERR "$P timeout waiting for lock\n";
93 1         5 return;
94             }
95 2751         5897794 Time::HiRes::sleep $PAUSE_LENGTH * (1 + 2 * rand());
96 2751 50       25106 if (Time::HiRes::time > $last_check + $HEARTBEAT_CHECK) {
97 0 0       0 $P && print STDERR "$P check heartbeat of lock holder\n";
98 0         0 _ping_oldest_file($dir);
99 0         0 $last_check = Time::HiRes::time;
100             }
101 2751         8546 ($filename,$now) = _create_lockfile( $dir, "shared" );
102 2751         7267 $TMPFILE{ $filename } = _pid();
103             }
104 3 50       16 $P && print STDERR "$P lock successful to $filename\n";
105 3         31 $LOCK{$dir}{_pid()} = $filename;
106 3         19 1;
107             }
108              
109             sub unlock {
110 14     14 1 30013435 my ($dir) = @_;
111 14 100       110 if (!defined $LOCK{$dir}) {
112 1 50       202 return if __inGD();
113 1         6 $errstr = "lock for '$dir' not held by " . _pid()
114             . " nor any proc";
115 1         543 carp "Dir::Flock::unlock: $errstr";
116 1         8 return;
117             }
118 13         79 my $filename = delete $LOCK{$dir}{_pid()};
119 13 50       112 if (!defined($filename)) {
120 0 0       0 return if __inGD();
121 0         0 $errstr = "lock for '$dir' not held by " . _pid();
122 0         0 carp "Dir::Flock::unlock: $errstr";
123 0         0 return;
124             }
125 13 50       66 $_DEBUG && print STDERR _pid()," unlocking $filename\n";
126 13 50       386 if (! -f $filename) {
127 0 0       0 return if __inGD();
128 0         0 $errstr = "lock file '$filename' is missing";
129             carp "Dir::Flock::unlock: lock file is missing ",
130 0         0 %{$LOCK{$dir}};
  0         0  
131 0         0 return;
132             }
133 13         827 my $z = unlink($filename);
134 13 50       156 if ($z) {
135 13 50       77 $_DEBUG && print STDERR _pid()," deleted $filename\n";
136 13         61 delete $TMPFILE{$filename};
137 13         72 return $z;
138             }
139 0 0       0 return if __inGD();
140 0         0 $errstr = "unlink called failed on file '$filename'";
141 0         0 carp "Dir::Flock::unlock: failed to unlink lock file ",
142             "'$filename'";
143 0         0 return;
144             }
145              
146              
147              
148             ### flock semantics
149              
150             sub flock {
151 5     5 1 10018887 my ($dir, $op) = @_;
152 5 100       140 if ($op & LOCK_UN) {
153 2         17 return unlock($dir);
154             }
155 3         66 my $timeout = undef;
156 3 100       76 if ($op & LOCK_NB) {
157 1         6 $timeout = 0;
158             }
159 3 50       66 if ($op & LOCK_EX) {
160 3         43 return lock_ex($dir,$timeout);
161             }
162 0 0       0 if ($op & LOCK_SH) {
163 0         0 return lock_sh($dir,$timeout);
164             }
165 0         0 $errstr = "invalid flock operation '$op'";
166 0         0 carp "Dir::Flock::flock: invalid operation";
167 0         0 return;
168             }
169              
170              
171             ### scope semantics
172              
173 0     0 1 0 sub lockobj { goto &lockobj_ex }
174              
175             sub lockobj_ex {
176 0     0 1 0 my ($dir, $timeout) = @_;
177 0         0 my $ok = lock_ex($dir,$timeout);
178 0 0       0 return if !$ok;
179 0         0 return bless \$dir, 'Dir::Flock::SyncObject2';
180             }
181              
182             sub lockobj_sh {
183 0     0 1 0 my ($dir, $timeout) = @_;
184 0         0 my $ok = lock_sh($dir,$timeout);
185 0 0       0 return if !$ok;
186 0         0 return bless \$dir, 'Dir::Flock::SyncObject2';
187             }
188              
189             sub Dir::Flock::SyncObject2::DESTROY {
190 0     0   0 my $self = shift;
191 0         0 my $dir = $$self;
192 0         0 my $ok = unlock($dir);
193 0 0 0     0 if (!$ok && !__inGD()) {
194             # $errstr set in unlock
195 0         0 carp "unlock: failed for dir '$dir' as sync object went out of scope";
196             }
197 0         0 return;
198             }
199              
200             ### block semantics
201              
202 0     0 1 0 sub sync (&$;$) { goto &sync_ex }
203              
204             sub sync_ex (&$;$) {
205 0     0 1 0 my ($code, $dir, $timeout) = @_;
206 0 0       0 if (!lock_ex($dir,$timeout)) {
207             # $errstr set in lock_ex
208 0         0 return;
209             }
210 0         0 my @r;
211 0 0       0 if (wantarray) {
212 0         0 @r = eval { $code->() };
  0         0  
213             } else {
214 0         0 $r[0] = eval { $code->() };
  0         0  
215             }
216 0         0 unlock($dir);
217 0 0       0 if ($@) {
218 0         0 $errstr = "error from sync_ex BLOCK: $@";
219 0         0 die $@;
220             }
221 0 0       0 wantarray ? @r : $r[0];
222             }
223              
224             sub sync_sh (&$;$) {
225 0     0 1 0 my ($code, $dir, $timeout) = @_;
226 0 0       0 if (!lock_sh($dir,$timeout)) {
227             # $errstr set in lock_sh
228 0         0 return;
229             }
230 0         0 my @r;
231 0 0       0 if (wantarray) {
232 0         0 @r = eval { $code->() };
  0         0  
233             } else {
234 0         0 $r[0] = eval { $code->() };
  0         0  
235             }
236 0         0 unlock($dir);
237 0 0       0 if ($@){
238 0         0 $errstr = "error from sync_sh BLOCK: $@";
239 0         0 die $@;
240             }
241 0 0       0 wantarray ? @r : $r[0];
242             }
243              
244             ### utilities
245              
246             sub _host {
247             $ENV{HOSTNAME} || ($^O eq 'MSWin32' && $ENV{COMPUTERNAME})
248 23430 0 0 23430   105883 || "localhost";
      33        
249             }
250              
251             sub _pid {
252 23429     23429   45090 my $host = _host();
253 23429 50       314806 join("_", $host, $$, $INC{"threads.pm"} ? threads->tid : ());
254             }
255              
256             sub _create_lockfile {
257 11694     11694   48228 my ($dir,$type) = @_;
258 11694   50     29377 $type ||= "excl";
259 11694         27986 my $now = Time::HiRes::time;
260 11694         40419 my $file = sprintf "$dir/%s_%s_%s_%s", $LOCKFILE_STUB,
261             $now, $type, _pid();
262 11694         1081116 open my $fh, ">>", $file;
263 11694         167588 close $fh;
264 11694         114190 return ($file,$now);
265             }
266              
267             sub _oldest_file {
268 11695     11695   30380 my ($dir, $excl) = @_;
269 11695         17785 my $dh;
270 11695         29485 _refresh_dir($dir); # is this necessary? is this sufficient?
271 11695 50       36778 if ($CHECK_DELAY) {
272             # if lock dir is local and very responsive, then two competing
273             # processes may thing they each obtained the lock. A small pause
274             # between lockfile creation and file check should mitigate this.
275 11695         13130370 Time::HiRes::sleep $CHECK_DELAY;
276             }
277 11695         1226177 my @f1 = sort glob("$dir/$LOCKFILE_STUB*");
278 11695 50       71504 if ($excl) {
279 0         0 @f1 = grep /_excl_/, @f1;
280             }
281 11695 50       99560 @f1 > 0 && $f1[0];
282             }
283              
284             sub _ping_oldest_file {
285 1     1   12 my ($dir,$excl) = @_;
286 1         12 my $file = _oldest_file($dir,$excl);
287 1 50       5 return unless $file;
288 1         3 my $file0 = $file;
289 1         74 $file0 =~ s/.*$LOCKFILE_STUB.//;
290 1         18 my ($time, $type, $host, $pid, $tid) = split /_/, $file0;
291 1         24 $pid =~ s/\D+$//;
292 1 50       6 $_DEBUG && print STDERR _pid(), ": ping host=$host pid=$pid tid=$tid\n";
293 1 50       5 $_DEBUG && print STDERR "$dir holds:\n", join(" ",glob("$dir/*")),"\n";
294 1         2 my $status;
295              
296              
297             # TODO: what if $tid is defined? How do you signal a thread
298             # and how do you signal or terminate a remote thread?
299            
300 1 50 33     4 if ($host eq _host() || $host eq 'localhost') {
301             # TODO: more robust way to inspect process on local machine.
302             # kill 'ZERO',... can mislead for a number of reasons, such as
303             # if the process is owned by a different user.
304 1         25 $status = kill 'ZERO', $pid;
305 1 50       7 $_DEBUG && print STDERR _pid(), " local kill ZERO => $pid: $status\n";
306             } else {
307             # TODO: need a more robust way to inspect a process on a remote machine
308 0         0 my $c1 = system("ssh $host kill -0 $pid");
309 0         0 $status = ($c1 == 0);
310 0 0       0 $_DEBUG && print STDERR _pid(),
311             " remote kill ZERO => $host:$pid: $status\n";
312             }
313 1 50       5 if (! $status) {
314 1         94 warn "Dir::Flock: lock holder that created $file appears dead\n";
315 1         71 unlink $file;
316             }
317             }
318              
319             sub _refresh_dir {
320             # https://stackoverflow.com/a/30630912
321             # "Within a given process, calling opendir and closedir on the
322             # parent directory of a file invalidates the NFS cache."
323 11714     11714   23086 my $dir = shift;
324 11714         17137 my $dh;
325 11714         353517 opendir $dh, $dir;
326 11714         143187 closedir $dh;
327 11714         68164 return;
328             }
329              
330             sub _validate_dir {
331 19     19   177 my $dir = shift;
332 19 50       804 if (! -d $dir) {
333 0         0 $errstr = "lock dir '$dir' is not a directory";
334 0         0 carp "Dir::Flock::lock: $errstr";
335 0         0 return;
336             }
337 19 0 33     581 if (! -r $dir && -w $dir && -x $dir) {
      33        
338 0         0 $errstr = "lock dir '$dir' is not an accessible directory";
339 0         0 carp "Dir::Flock::lock: $errstr";
340 0         0 return;
341             }
342 19         193 _refresh_dir($dir);
343 19         119 1;
344             }
345              
346             BEGIN {
347 14 50   14   123 if (defined(${^GLOBAL_PHASE})) {
348 14 50       1351 eval 'sub __inGD(){%{^GLOBAL_PHASE} eq q{DESTRUCT} && __END()};1'
349             } else {
350 0         0 require B;
351 0         0 eval 'sub __inGD(){${B::main_cv()}==0 && __END()};1'
352             }
353             }
354              
355             END {
356 14     13   23277 my $p = _pid();
357 14     14   97 no warnings 'redefine';
  14         33  
  14         2601  
358 13     1   400 *DB::DB = sub {};
359 13         311 *__inGD = sub () { 1 };
360 13         290 unlink grep{ $TMPFILE{$_} eq $p } keys %TMPFILE;
  0            
361             }
362              
363             1;
364              
365             =head1 NAME
366              
367             Dir::Flock - advisory locking of a dedicated directory
368              
369              
370              
371             =head1 VERSION
372              
373             0.09
374              
375              
376              
377             =head1 SYNOPSIS
378              
379             use Dir::Flock;
380             my $dir = Dir::Flock::getDir("/home/mob/projects/foo");
381             my $success = Dir::Flock::lock($dir);
382             # ... synchronized code
383             $success = Dir::Flock::unlock($dir);
384              
385             # flock semantics
386             use Fcntl ':flock';
387             $success = Dir::Flock::flock($dir, LOCK_EX | LOCK_NB);
388             ...
389             Dir::Flock::flock($dir, LOCK_UN);
390              
391             # mutex/scoping semantics
392             {
393             my $lock = Dir::Flock::lockobj($dir);
394             ... synchronized code ...
395             } # lock released when $lock goes out of scope
396              
397             # code ref semantics
398             Dir::Flock::sync {
399             ... synchronized code ...
400             }, $dir
401              
402              
403              
404             =head1 DESCRIPTION
405              
406             C implements advisory locking on a directory, similar
407             to how the builtin L performs advisory
408             locking on a file. In addition to helping facilitate synchronized
409             access to a directory, C functions can be adapted to
410             provide synchronized access to any resource across multiple
411             processes and even across multiple hosts (where the same directory
412             has been mounted). It overcomes some of the limitations of
413             C such as heritability of locks over forks and threads,
414             or being able to lock files on a networked file system (like NFS).
415              
416              
417             =head2 Algorithm
418              
419             File locking is difficult on NFS because, as I understand it, each
420             node maintains a cache that includes file contents and file metadata.
421             When a system call wants to check whether a lock exists on a file,
422             the filesystem driver might inspect the cached file rather than
423             the file on the server, and it might miss an action taken by another
424             node to lock a file.
425              
426             The cache is not used, again, as I understand it, when the filesystem
427             driver reads a directory. If advisory locking is accomplished through
428             reading the contents of a directory, it will not be affected by NFS's
429             caching behavior.
430              
431             To acquire a lock in a directory, this module writes an empty file
432             into the directory. The name of the file encodes the host and process
433             id that is requesting the lock, and a timestamp of when the request
434             was made. Then it checks if this new file is the "oldest"
435             file in the directory. If it is the oldest file, then the process
436             has acquired the lock. If there is already an older file in the
437             directory, then the process specified by that file possesses the lock,
438             and we must try again later. To unlock the directory, the module
439             simply deletes the file in the directory that represents its lock.
440              
441             =head2 Semantics
442              
443             This module offers several different semantics for advisory
444             locking of a directory.
445              
446             =head3 functional semantics
447              
448             The core L and
449             L functions begin and end advisory
450             locking on a directory. All of the other semantics are implemented in
451             terms of these functions.
452              
453             $ok = Dir::Flock::lock( "/some/path" );
454             $ok = Dir::Flock::lock( "/some/path", $timeout );
455             $ok = Dir::Flock::unlock( "/some/path" );
456              
457             =head3 flock semantics
458              
459             The function L emulates the Perl
460             L builtin, accepting the same arguments
461             for the operation argument.
462              
463             use Fcntl ':flock';
464             $ok = Dir::Flock::flock( "/some/path", LOCK_EX );
465             ...
466             $ok = Dir::Flock::flock( "/some/path", LOCK_UN );
467              
468             =head3 scope-oriented semantics
469              
470             The L function returns an
471             object representing a directory lock. The lock is released
472             when the object goes out of scope.
473              
474             {
475             my $lock = Dir::Flock::lockobj( "/some/path" );
476             ...
477             } # $lock out of scope, lock released
478              
479             =head3 BLOCK semantics
480              
481             The L accepts a block of code or other
482             code reference, to be executed with an advisory lock on a
483             directory.
484              
485             Dir::Flock::sync {
486             ... synchronized code ...
487             } "/some/path";
488              
489              
490             =head1 FUNCTIONS
491              
492             Most functions return a false value and set the package variable
493             C<$Dir::Flock::errstr> if they are unsuccessful.
494              
495              
496             =head2 lock
497              
498             =head2 lock_ex
499              
500             =head2 $success = Dir::Flock::lock( $directory [, $timeout ] )
501              
502             =head2 $success = Dir::Flock::lock_ex( $directory [, $timeout ] )
503              
504             Attempts to obtain an I lock on the given directory. While
505             the directory is locked, the C or C call on the
506             same directory from
507             other processes or threads will block until the directory is unlocked
508             (see L<"unlock">). Returns true if the lock was successfully acquired.
509             Note that the first argument is a path name, not a directory I.
510              
511             If an optional C<$timeout> argument is provided, the function will
512             try for at least C<$timeout> seconds to acquire the lock, and return
513             a false value if it is not successful in that time. Use a timeout of
514             zero to make a "non-blocking" request for an exclusive lock.
515              
516              
517             =head2 lock_sh
518              
519             =head2 $success = Dir::Flock::lock_sh( $directory [, $timeout ] )
520              
521             Attempts to obtain a I lock on the given directory.
522             While there are shared locks on a directory, other calls to C
523             may also receive a shared lock on the directory but calls to
524             C/C on the directory will block until all
525             shared locks are removed.
526              
527             If an optional C<$timeout> argument is provided, the function will
528             try for at least C<$timeout> seconds to acquire the shared lock, and
529             return a false value if it is not successful in that time.
530             Use a timeout of zero to make a "non-blocking" shared lock request.
531              
532              
533             =head2 unlock
534              
535             =head2 $success = Dir::Flock::unlock( $directory )
536              
537             Releases the exclusive or shared lock on the given directory held
538             by this process. Returns a false value if the current process did
539             not possess the lock on the directory.
540              
541              
542             =head2 getDir
543              
544             =head2 $tmp_directory = Dir::Flock::getDir( $root [, $persist] )
545              
546             Creates a temporary and empty directory in a subdirectory of C<$root>
547             that is suitable for use as a synchronization directory. The directory
548             will automatically be cleaned up when the process that called this
549             function exits, unless the optional C<$persist> argument is set to
550             a true value. The C<$persist> argument can be used to create a
551             directory that can be used for synchronization by other processes
552             or on other hosts after the lifetime of the current program.
553              
554             If the input to C is a filename rather than a directory name,
555             a new subdirectory will be created in the directory where the file
556             is located.
557              
558              
559             =head2 flock
560              
561             =head2 $success = Dir::Flock::flock( $dir, $op )
562              
563             Acquires and releases advisory locks on the given directory
564             with the same semantics as the Perl builtin
565             L function.
566              
567              
568              
569             =head2 lockobj
570              
571             =head2 lockobj_ex
572              
573             =head2 $lock = Dir::Flock::lockobj( $dir [, $timeout] );
574              
575             =head2 $lock = Dir::Flock::lockobj_ex( $dir [, $timeout] );
576              
577             Attempts to acquire an exclusive advisory lock for the given
578             directory. On success, returns a handle to the directory lock
579             with the feature that the lock will be released when the handle
580             goes out of scope. This allows you to use this module with
581             syntax such as
582              
583             {
584             my $lock = Dir::Flock::lockobj( "/some/path" );
585             ... synchronized code ...
586             }
587             # $lock out of scope, so directory lock released
588             ... unsynchronized code ...
589              
590             Optional C<$timeout> argument causes the function to block
591             for a maximum of C<$timeout> seconds attempting to acquire
592             the lock. If C<$timeout> is not provided or is C,
593             the function will block indefinitely while waiting for the
594             lock.
595              
596             Returns a false value and may sets C<$Dir::Flock::errstr> if the function
597             times out or is otherwise unable to acquire the directory lock.
598              
599             C is an alias for C.
600              
601              
602             =head2 lockobj_sh
603              
604             =head2 my $lock = Dir::Flock::lockobj_sh($dir [, $timeout])
605              
606             Analogue to L<"lockobj_ex">. Returns a reference to a shared lock
607             on a directory that will be released when the reference goes
608             out of scope.
609              
610             Returns a false value and may set C<$Dir::Flock::errstr> if the
611             function times out or otherwise fails to acquire a shared lock
612             on the directory.
613              
614              
615             =head2 sync
616              
617             =head2 sync_ex
618              
619             =head2 $result = Dir::Flock::sync CODE $dir [, $timeout]
620              
621             =head2 @result = Dir::Flock::sync_ex CODE $dir [, $timeout]
622              
623             Semantics for executing a block of code while there is an
624             advisory exclusive lock on the given directory. The code can
625             be evaluated in both scalar or list contexts. An optional
626             C<$timeout> argument will cause the function to give up and
627             return a false value if the lock cannot be acquired after
628             C<$timeout> seconds. Callers should be careful to distinguish
629             cases where the specified code reference returns nothing and
630             where the C function fails to acquire the lock and returns nothing.
631             One way to distinguish these cases is to check the value of
632             C<$Dir::Flock::errstr>, which will generally be set if there
633             was an issue with the locking mechanics.
634              
635             The lock is released in the event that the given C
636             produces a fatal error.
637              
638              
639             =head2 sync_sh
640              
641             =head2 $result = Dir::Flock::sync_sh CODE $dir [, $timeout]
642              
643             =head2 @result = Dir::Flock::sync_sh CODE $dir [, $timeout]
644              
645             Analogue of L<"sync_ex"> but executes the code block while
646             there is an advisory shared lock on the given directory.
647              
648              
649             =head1 DEPENDENCIES
650              
651             C requires L where the C
652             function has subsecond resolution.
653              
654              
655             =head1 EXPORTS
656              
657             Nothing is exported from C by default, but all of
658             the functions documented here may be exported by name.
659              
660             Many of the core functions of C have the same name
661             as Perl builtin functions or functions from other popular modules,
662             so users should be wary of importing functions from this module
663             into their working namespace.
664              
665              
666              
667             =head1 VARIABLES
668              
669             =head2 PAUSE_LENGTH
670              
671             =head2 $Dir::Flock::PAUSE_LENGTH
672              
673             C<$Dir::Flock::PAUSE_LENGTH> is the average number of seconds that
674             the module will wait after a failed attempt to acquire a lock before
675             attempting to acquire it again. The default value is 0.001,
676             which is a good setting for having a high throughput when the
677             synchronized operations take a short amount of time. In contexts
678             where the synchronized operations take a longer time, it may
679             be appropriate to increase this value to reduce busy-waiting CPU
680             utilization.
681              
682             =cut
683              
684             # also under VARIABLES: HEARTBEAT_CHECK
685              
686             # =head1 ENVIRONMENT => DIR_FLOCK_DEBUG
687              
688             # =cut
689              
690              
691              
692             =head1 LIMITATIONS
693              
694             C requires that the function values of L
695             have subsecond resolution
696              
697              
698             If C is going to be used to synchronize a networked
699             directory across multiple hosts, it is imporant that the clocks
700             be synchronized between those hosts. Otherwise, a host with a
701             "fast" clock will be able to steal locks from a host with a
702             "slow" clock.
703              
704              
705             =head1 SEE ALSO
706              
707             Many other modules have taken a shot at advisory locking over
708             NFS, including L, L.
709             L, and L.
710              
711              
712             =head1 SUPPORT
713              
714             You can find documentation for this module with the perldoc command.
715              
716             perldoc Dir::Flock
717              
718              
719             You can also look for information at:
720              
721             =over 4
722              
723             =item * CPAN Ratings
724              
725             L
726              
727             =item * Emob@cpan.orgE
728              
729             With the decommissioning of http://rt.cpan.org/,
730             please send bug reports and feature requests
731             directly to the author's email address.
732              
733             =back
734              
735              
736              
737              
738             =head1 AUTHOR
739              
740             Marty O'Brien, Emob@cpan.orgE
741              
742              
743              
744              
745             =head1 LICENSE AND COPYRIGHT
746              
747             Copyright (c) 2019-2021, Marty O'Brien
748              
749             This library is free software; you can redistribute it and/or modify
750             it under the same terms as Perl itself, either Perl version 5.8.8 or,
751             at your option, any later version of Perl 5 you may have available.
752              
753             See http://dev.perl.org/licenses/ for more information.
754              
755             =cut
756              
757              
758             =begin TODO
759              
760             Heartbeat
761              
762             a running process should be able to update the timestamp of
763             their lockfiles (either the mtime known to the filesystem or
764             in the file data themselves) to let other processes (on the
765             same and other hosts) know that the locking process is still
766             alive. Can you do that without releasing the lock?
767              
768             Include heartbeat data in the file names? "touch" lock files
769             at the heartbeat so that the mtime's are updated?
770              
771             Threads
772              
773             In _ping_oldest_file , how to detect whether a thread is
774             still alive? How to detect whether a process or thread on
775             a remote machine is still alive?
776              
777             If a SyncObject2 is inherited in a fork or a thread,
778             will DESTROY release its lock?
779              
780             =end TODO