#---------- utility functions ----------
+sub lockfile ($$) {
+ my ($fh, $fn, $flockmode) = @_;
+ for (;;) {
+ close $fh;
+ open $fh, '+>', $fn or fail "open/create $fn for lock: $!";
+ if (!flock $fh, $lockmode) {
+ if ($lockmode & LOCK_NB and $! == EWOULDBLOCK) {
+ return 0; # ok then
+ }
+ fail "lock $fn".
+ (($flockmode & ~LOCK_NB) == LOCK_SH ? " (shared)" : "").
+ ": $!";
+ }
+ stat $fh or fail "stat opened $fn: $!";
+ my $fh_ino = ((stat _)[1]);
+ if (!stat $fn) {
+ $! == ENOENT or fail "stat $fn: $!";
+ next;
+ }
+ my $fn_ino = ((stat _)[1]);
+ return 1 if $fn_ino == $fh_ino;
+ # oh dear
+ }
+}
+
sub xread {
my $length = shift;
my $buffer = "";
}
sub clonefetch () {
- open LOCK, "+>", $lock or fail "open/create $lock: $!";
- flock LOCK, LOCK_EX or fail "lock exclusive $lock: $!";
+ lockfile \*LOCK, $lock, LOCK_EX;
my $exists = lstat $gitd;
$exists or $!==ENOENT or fail "lstat $gitd: $!";
}
servinfo "sharing";
- flock LOCK, LOCK_UN or fail "unlock $lock: $!";
- flock LOCK, LOCK_SH or fail "lock shared $lock: $!";
- # actually, just relocking as shared would have the same semantics
- # but it's best to be explicit
+ lockfile \*LOCK, $lock, LOCK_SH; # NB releases and relocks
if (chdir $gitd) {
return 1;
sub housekeepingcheck ($$) {
my ($dofork, $force) = @_;
- open HLOCK, "+>", "Housekeeping.lock"
or fail "open/create Housekeeping.lock: $!";
if (!$force) {
- if (flock HLOCK, LOCK_EX|LOCK_NB) {
+ if (!lockfile \*HLOCK, "Housekeeping.lock", LOCK_EX|LOCK_NB) {
logm 'debug', "housekeeping lock taken, not running";
close HLOCK;
return 0;