]> git.proxmox.com Git - pve-common.git/blobdiff - src/PVE/Tools.pm
tools: unbless errors in run_fork_with_timeout
[pve-common.git] / src / PVE / Tools.pm
index f43424bb7307095debd575840b6495bb828eaf48..53ac83fd2b744366706d6354c4c4434aa183f614 100644 (file)
@@ -369,6 +369,7 @@ sub run_command {
     my $afterfork;
     my $noerr;
     my $keeplocale;
+    my $quiet;
 
     eval {
 
@@ -395,6 +396,8 @@ sub run_command {
                $noerr = $param{$p};
            } elsif ($p eq 'keeplocale') {
                $keeplocale = $param{$p};
+           } elsif ($p eq 'quiet') {
+               $quiet = $param{$p};
            } else {
                die "got unknown parameter '$p' for run_command\n";
            }
@@ -497,7 +500,7 @@ sub run_command {
                            waitpid ($pid, 0);
                            die $err;
                        }
-                   } else {
+                   } elsif (!$quiet) {
                        print $buf;
                        *STDOUT->flush();
                    }
@@ -517,7 +520,7 @@ sub run_command {
                            waitpid ($pid, 0);
                            die $err;
                        }
-                   } else {
+                   } elsif (!$quiet) {
                        print STDERR $buf;
                        *STDERR->flush();
                    }
@@ -901,6 +904,13 @@ sub next_spice_port {
     return next_unused_port(61000, 61099, $family, $address);
 }
 
+sub must_stringify {
+       my ($value) = @_;
+       eval { $value = "$value" };
+       return "error turning value into a string: $@" if $@;
+       return $value;
+}
+
 # sigkill after $timeout  a $sub running in a fork if it can't write a pipe
 # the $sub has to return a single scalar
 sub run_fork_with_timeout {
@@ -932,7 +942,7 @@ sub run_fork_with_timeout {
            $pipe_out->flush();
        };
        if (my $err = $@) {
-           print {$pipe_out} encode_json({ error => $err });
+           print {$pipe_out} encode_json({ error => must_stringify($err) });
            $pipe_out->flush();
            POSIX::_exit(1);
        }
@@ -978,49 +988,40 @@ sub run_fork {
 sub df {
     my ($path, $timeout) = @_;
 
-    my $res = {
-       total => 0,
-       used => 0,
-       avail => 0,
+    my $df = sub { return Filesys::Df::df($path, 1) };
+
+    my $res = eval { run_fork_with_timeout($timeout, $df) } // {};
+    warn $@ if $@;
+
+    # untaint the values
+    my ($blocks, $used, $bavail) = map { defined($_) ? (/^(\d+)$/) : 0 }
+       $res->@{qw(blocks used bavail)};
+
+    return {
+       total => $blocks,
+       used => $used,
+       avail => $bavail,
     };
+}
 
-    my $pipe = IO::Pipe->new();
-    my $child = fork();
-    if (!defined($child)) {
-       warn "fork failed: $!\n";
-       return $res;
-    }
+sub du {
+    my ($path, $timeout) = @_;
 
-    if (!$child) {
-       $pipe->writer();
-       eval {
-           my $df = Filesys::Df::df($path, 1);
-           print {$pipe} "$df->{blocks}\n$df->{used}\n$df->{bavail}\n"
-               if defined($df);
-           $pipe->close();
-       };
-       if (my $err = $@) {
-           warn $err;
-           POSIX::_exit(1);
-       }
-       POSIX::_exit(0);
-    }
+    my $size;
 
-    $pipe->reader();
+    $timeout //= 10;
 
-    my $readvalues = sub {
-       $res->{total} = int(((<$pipe> // 0) =~ /^(\d*)$/)[0]);
-       $res->{used}  = int(((<$pipe> // 0) =~ /^(\d*)$/)[0]);
-       $res->{avail} = int(((<$pipe> // 0) =~ /^(\d*)$/)[0]);
-    };
-    eval {
-       run_with_timeout($timeout, $readvalues);
+    my $parser = sub {
+       my $line = shift;
+
+       if ($line =~ m/^(\d+)\s+total$/) {
+           $size = $1;
+       }
     };
-    warn $@ if $@;
-    $pipe->close();
-    kill('KILL', $child);
-    waitpid($child, 0);
-    return $res;
+
+    run_command(['du', '-scb', $path], outfunc => $parser, timeout => $timeout);
+
+    return $size;
 }
 
 # UPID helper