This runs subroutine in a forked process
and kills it after a timeout
---
 src/PVE/Tools.pm | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
index da7da5d..0bf94ae 100644
--- a/src/PVE/Tools.pm
+++ b/src/PVE/Tools.pm
@@ -841,6 +841,49 @@ sub next_spice_port {
     return next_unused_port(61000, 61099, $family, $address);
 }
 
+# sigkill a $sub running in a fork if it can't write a pipe after $timeout
+# the $sub has to return a single scalar
+sub run_or_get_killed {
+    my ($sub, $timeout) = @_;
+
+    my $res;
+
+    my $pipe = IO::Pipe->new();
+    my $child = fork();
+    if (!defined($child)) {
+       warn "fork failed: $!\n";
+       return $res;
+    }
+
+    if (!$child) {
+       $pipe->writer();
+       eval {
+           $res = $sub->();
+           print {$pipe} "$res";
+           $pipe->close();
+       };
+       if (my $err = $@) {
+           warn $err;
+           POSIX::_exit(1);
+       }
+       POSIX::_exit(0);
+    }
+
+    $pipe->reader();
+
+    my $readvalues = sub {
+       $res = (<$pipe> =~ /^(.*)$/)[0];
+    };
+    eval {
+       run_with_timeout($timeout, $readvalues);
+    };
+    warn $@ if $@;
+    $pipe->close();
+    kill('KILL', $child);
+    waitpid($child, 0);
+    return $res;
+}
+
 # NOTE: NFS syscall can't be interrupted, so alarm does
 # not work to provide timeouts.
 # from 'man nfs': "Only SIGKILL can interrupt a pending NFS operation"
-- 
2.11.0


_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to