+ return wantarray ? ($cmd, $data) : $data;
+};
+
+my $kill_worker = sub {
+ my ($self) = @_;
+
+ return if !$self->{cpid};
+ return if $self->{__already_killed};
+
+ $self->{__already_killed} = 1;
+
+ close($self->{child}) if defined($self->{child});
+
+ kill(9, $self->{cpid});
+ waitpid($self->{cpid}, 0);
+};
+
+my $sendcmd = sub {
+ my ($self, $cmd, $data, $expect_tag) = @_;
+
+ $expect_tag = '>' if !$expect_tag;
+
+ my ($restag, $raw);
+ my $code = sub {
+ &$writedata($self->{child}, $cmd, $data) if $expect_tag ne 'S';
+ ($restag, $raw) = &$readdata($self->{child});
+ };
+ eval { PVE::Tools::run_with_timeout($self->{timeout}, $code); };
+ if (my $err = $@) {
+ &$kill_worker($self);
+ die $err;
+ }
+ if ($restag eq 'E') {
+ die $raw if $raw;
+ die "unknown error\n";