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