package PVE::Tools;
use strict;
-use POSIX;
+use POSIX qw(EINTR);
use IO::Socket::INET;
use IO::Select;
use File::Basename;
our @EXPORT_OK = qw(
lock_file
+lock_file_full
run_command
file_set_contents
file_get_contents
my $lock_handles = {};
-sub lock_file {
- my ($filename, $timeout, $code, @param) = @_;
+sub lock_file_full {
+ my ($filename, $timeout, $shared, $code, @param) = @_;
$timeout = 10 if !$timeout;
+ my $mode = $shared ? LOCK_SH : LOCK_EX;
+
my $lock_func = sub {
if (!$lock_handles->{$$}->{$filename}) {
$lock_handles->{$$}->{$filename} = new IO::File (">>$filename") ||
die "can't open file - $!\n";
}
- if (!flock ($lock_handles->{$$}->{$filename}, LOCK_EX|LOCK_NB)) {
+ if (!flock ($lock_handles->{$$}->{$filename}, $mode|LOCK_NB)) {
print STDERR "trying to aquire lock...";
- if (!flock ($lock_handles->{$$}->{$filename}, LOCK_EX)) {
+ my $success;
+ while(1) {
+ $success = flock($lock_handles->{$$}->{$filename}, $mode);
+ # try again on EINTR (see bug #273)
+ if ($success || ($! != EINTR)) {
+ last;
+ }
+ }
+ if (!$success) {
print STDERR " failed\n";
die "can't aquire lock - $!\n";
}
return $res;
}
+
+sub lock_file {
+ my ($filename, $timeout, $code, @param) = @_;
+
+ return lock_file_full($filename, $timeout, 0, $code, @param);
+}
+
sub file_set_contents {
my ($filename, $data, $perm) = @_;
my $logfunc;
my $input;
my $output;
+ my $afterfork;
eval {
$errfunc = $param{$p};
} elsif ($p eq 'logfunc') {
$logfunc = $param{$p};
+ } elsif ($p eq 'afterfork') {
+ $afterfork = $param{$p};
} else {
die "got unknown parameter '$p' for run_command\n";
}
local $SIG{ALRM} = sub { die "got timeout\n"; } if $timeout;
$oldtimeout = alarm($timeout) if $timeout;
+ &$afterfork() if $afterfork;
+
if (ref($writer)) {
print $writer $input if defined $input;
close $writer;
my ($task, $filename) = upid_decode($upid);
my $fh = IO::File->new($filename, "r");
return "unable to open file - $!" if !$fh;
- my $maxlen = 1024;
+ my $maxlen = 4096;
sysseek($fh, -$maxlen, 2);
my $readbuf = '';
my $br = sysread($fh, $readbuf, $maxlen);