[pve-devel] [PATCH common v3] run_fork_with_timeout: allow returning complex structures

Thomas Lamprecht t.lamprecht at proxmox.com
Tue Sep 12 13:25:30 CEST 2017


Encode the result or the error in JSON. This way complex objects or
exceptions may be passed to the parent in a generic way.

This allows to remove the second pipe 'pipe_err'.

Allow also to return undef without any warnings to our caller.
This avoids a "use of uninitialized variable ..." warning

Signed-off-by: Thomas Lamprecht <t.lamprecht at proxmox.com>
---

changes v2 -> v3:
 * adapt Dietmars idea and use JSON for serialization, which then
   allows to omit the second pipe

 src/PVE/Tools.pm | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm
index 81662b1..3080b3e 100644
--- a/src/PVE/Tools.pm
+++ b/src/PVE/Tools.pm
@@ -20,6 +20,7 @@ use base 'Exporter';
 use URI::Escape;
 use Encode;
 use Digest::SHA;
+use JSON;
 use Text::ParseWords;
 use String::ShellQuote;
 use Time::HiRes qw(usleep gettimeofday tv_interval alarm);
@@ -905,7 +906,6 @@ sub run_fork_with_timeout {
     my $res;
     my $error;
     my $pipe_out = IO::Pipe->new();
-    my $pipe_err = IO::Pipe->new();
 
     # disable pending alarms, save their remaining time
     my $prev_alarm = alarm 0;
@@ -922,35 +922,33 @@ sub run_fork_with_timeout {
 
     if (!$child) {
 	$pipe_out->writer();
-	$pipe_err->writer();
 
 	eval {
 	    $res = $sub->();
-	    print {$pipe_out} "$res";
+	    print {$pipe_out} encode_json({ result => $res });
 	    $pipe_out->flush();
 	};
 	if (my $err = $@) {
-	    print {$pipe_err} "$err";
-	    $pipe_err->flush();
+	    print {$pipe_out} encode_json({ error => $err });
+	    $pipe_out->flush();
 	    POSIX::_exit(1);
 	}
 	POSIX::_exit(0);
     }
 
     $pipe_out->reader();
-    $pipe_err->reader();
 
     my $readvalues = sub {
 	local $/ = undef;
-	$res = <$pipe_out>;
-	$error = <$pipe_err>;
+	my $child_res = decode_json(scalar<$pipe_out>);
+	$res = $child_res->{result};
+	$error = $child_res->{error};
     };
     eval {
 	run_with_timeout($timeout, $readvalues);
     };
     warn $@ if $@;
     $pipe_out->close();
-    $pipe_err->close();
     kill('KILL', $child);
     waitpid($child, 0);
 
-- 
2.11.0





More information about the pve-devel mailing list