On Thu, 10 Jan 2002 10:00:50 +0000 (GMT), Richard Smith wrote: >I use an indirect method for locking files, which works fine on all platforms. >I borrowed the method from a Matthew Wright script
Uh-oh... >(tweaked a bit for my own >taste in Perl style). The subroutines are as follows: > >sub lockFile { > # Create a lock file for the file passed as a parameter. > # If no parameter is passed, return a false value. > $_ = shift or return 0; No local()? > $_ = $_ . '.lock'; > my $i; > > for ($i = 0; $i < $timeOut; $i++) { > > (-e $_) > and sleep 1 > and next; > > open LOCK, ">$_" or &outputError("Can't create lock file", >$!); That's what I thought. You've got a race condition. ANother program might create the lockfile between your "the file does not exist" test, and your "I'll make it now". > print LOCK '0'; > close LOCK; > last; > > } There are better ways, to avoid the race condition. You can use sysopen(), which allows for more ways to create a file than the plain ">" and ">>" modes: such as the O_EXCL (flag) mode You need some constants from Fcntl. And sleeping in increments of 1 second is far too course. Either use a shorter sleep from Time::HiRes, or you could use the 4 argument select() to produce the time-out. You also need to delete the lockfile when you're through. That's dangerous: if your script dies, the lockfile won't be deleted. Unless you take care of that... Here's a draft, I haven't thoroughly tested it. use Fcntl; { my @lockfiles; END { foreach(@lockfiles) { unlink } # for 5.004 } sub lockFile ($) { #Create a lock file for the file passed as a parameter. my $lockfile = shift() . '.lock'; my $t0 = time; local *LOCK; until(sysopen LOCK, $lockfile, O_CREAT|O_TRUNC|O_EXCL|O_WRONLY) { die "Too many loops" if time-$t0 > 10; select undef, undef, undef, 0.1; } push @lockfiles, $lockfile; print LOCK $$; close LOCK; } } -- Bart.