From: Fabian Grünbichler Date: Wed, 10 Feb 2016 07:25:23 +0000 (+0100) Subject: Implement refcounting for flocks X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=commitdiff_plain;h=f127adaba550ef1fd5ccdbff258efdfc5f48a096 Implement refcounting for flocks This was already implemented in PVE::LXC::lock_aquire() and lock_release(). Enabling refcounting in the general PVE::Tools::lock_file() and lock_file_full() methods allows us to use one code base for flocking. Furthermore, we could get rid of various xx_no_lock methods that were required because the old non-refcounting version did not support nested flocks (the inner most flock would close the file handle and thus release the flock). --- diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index 9f08aa6..60ba8aa 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -126,15 +126,16 @@ sub lock_file_full { my $lock_func = sub { if (!$lock_handles->{$$}->{$filename}) { - $lock_handles->{$$}->{$filename} = new IO::File (">>$filename") || - die "can't open file - $!\n"; + my $fh = new IO::File(">>$filename") || + die "can't open file - $!\n"; + $lock_handles->{$$}->{$filename} = { fh => $fh, refcount => 0}; } - if (!flock ($lock_handles->{$$}->{$filename}, $mode|LOCK_NB)) { + if (!flock($lock_handles->{$$}->{$filename}->{fh}, $mode|LOCK_NB)) { print STDERR "trying to acquire lock..."; my $success; while(1) { - $success = flock($lock_handles->{$$}->{$filename}, $mode); + $success = flock($lock_handles->{$$}->{$filename}->{fh}, $mode); # try again on EINTR (see bug #273) if ($success || ($! != EINTR)) { last; @@ -146,6 +147,7 @@ sub lock_file_full { } print STDERR " OK\n"; } + $lock_handles->{$$}->{$filename}->{refcount}++; }; my $res; @@ -159,9 +161,12 @@ sub lock_file_full { $err = $@; } - if (my $fh = $lock_handles->{$$}->{$filename}) { - $lock_handles->{$$}->{$filename} = undef; - close ($fh); + if (my $fh = $lock_handles->{$$}->{$filename}->{fh}) { + my $refcount = --$lock_handles->{$$}->{$filename}->{refcount}; + if ($refcount <= 0) { + $lock_handles->{$$}->{$filename} = undef; + close ($fh); + } } if ($err) {