From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9]) by lore.proxmox.com (Postfix) with ESMTPS id 8539C1FF13B for ; Wed, 25 Feb 2026 16:20:12 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 8AA3B8257; Wed, 25 Feb 2026 16:20:19 +0100 (CET) From: Fiona Ebner To: pve-devel@lists.proxmox.com Subject: [PATCH guest-common v2 09/14] tunnel: redirect stderr to log function Date: Wed, 25 Feb 2026 16:18:32 +0100 Message-ID: <20260225151931.176335-10-f.ebner@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260225151931.176335-1-f.ebner@proxmox.com> References: <20260225151931.176335-1-f.ebner@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1772032764746 X-SPAM-LEVEL: Spam detection results: 0 AWL -0.009 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: SG6M7XQKGQWHLCUHQMXIRPZGGIEO7QJA X-Message-ID-Hash: SG6M7XQKGQWHLCUHQMXIRPZGGIEO7QJA X-MailFrom: f.ebner@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: With open2(), the stderr from the child process would just be printed directly making it impossible for the call site of the tunnel to filter the output. This is in preparation to add a 'pct mtunnel' command. When forking a tunnel to a node which does not support that command yet, the whole 'pct' usage documentation would be printed to the migration log and the call site would only see 'can't open tunnel - no reply' as an error. By capturing the stderr output too, the call site can detect that the failure happens because the target node is too old and avoid dumping the whole usage information. Signed-off-by: Fiona Ebner --- New in v2. src/PVE/Tunnel.pm | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/PVE/Tunnel.pm b/src/PVE/Tunnel.pm index 25e03b6..148a8e2 100644 --- a/src/PVE/Tunnel.pm +++ b/src/PVE/Tunnel.pm @@ -5,7 +5,7 @@ use warnings; use IO::File; use IO::Pipe; -use IPC::Open2; +use IPC::Open3 qw(open3); use JSON qw(encode_json decode_json); use POSIX qw( WNOHANG ); use Storable qw(dclone); @@ -66,12 +66,19 @@ sub read_tunnel { $timeout = 60 if !defined($timeout); my $reader = $tunnel->{reader}; + my $reader_stderr = $tunnel->{reader_stderr}; my $output; eval { PVE::Tools::run_with_timeout($timeout, sub { $output = <$reader>; }); }; - die "reading from tunnel failed: $@\n" if $@; + my $err = $@; + + while (my $line = <$reader_stderr>) { # $reader_stderr is set up as non-blocking + $tunnel->{log}->('warn', $line); + } + + die "reading from tunnel failed: $err\n" if $err; chomp $output if defined($output); @@ -145,13 +152,16 @@ sub fork_ssh_tunnel { my $full_cmd = [@$rem_ssh, '-o ExitOnForwardFailure=yes', @localtunnelinfo, @$cmd]; my $reader = IO::File->new(); + my $reader_stderr = IO::File->new(); my $writer = IO::File->new(); my $orig_pid = $$; my $cpid; - eval { $cpid = open2($reader, $writer, @$full_cmd); }; + eval { $cpid = open3($writer, $reader, $reader_stderr, @$full_cmd); }; + # Only read_tunnel() uses $reader_stderr and it never wants to wait. + $reader_stderr->blocking(0); my $err = $@; @@ -167,6 +177,7 @@ sub fork_ssh_tunnel { my $tunnel = { writer => $writer, reader => $reader, + reader_stderr => $reader_stderr, pid => $cpid, rem_ssh => $rem_ssh, log => $log, -- 2.47.3