all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Christoph Heiss <c.heiss@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH installer v2 6/6] fix #4872: run env: use run_command() for country detection
Date: Tue, 13 Feb 2024 16:14:03 +0100	[thread overview]
Message-ID: <20240213151405.1282639-7-c.heiss@proxmox.com> (raw)
In-Reply-To: <20240213151405.1282639-1-c.heiss@proxmox.com>

This fixes a rather longstanding issue [0][1] with the country
detection, in that it might get completely stuck and thus hangs the
installation.

This is due how Perl, signals and line reading interacts.

A minimal reproducer, how the installer currently works, looks like
this:
```
    #!/usr/bin/env perl

    use strict;
    use warnings;

    open (my $fh, '-|', 'sleep', '1000') or die;

    my $prev = alarm(2);
    eval {
	local $SIG{ALRM} = sub { die "timed out!\n" };

	my $line;
	while (defined ($line = <$fh>)) {
	    print "line: $line";
	}
    };

    alarm($prev);
    close($fh);
```

One might expect that this times out after 2 seconds, as specified in
`alarm(2)`. The thruth is that `$line = <$fh>` apparently prevents the
signal to go through. This then causes the installer to hang there
indefinitely, if `traceroute` never progresses - which seems to happen
on lots of (weird) networks, as evidently can be seen in the forum [1].

Proxmox::Sys::Command::run_command() handles of these weird cases, takes
care of the nitty-gritty details and - most importantly - interacts
properly with SIGALRM, so just use that instead.

This _should_ really fix that issue, but reproducing it 1:1 as part of
the installation process is _very_ hard, basically pure luck. But
rewriting the reproducer using run_command (in the exact same way that
this patch rewrites detect_country_tracing_to()) fixes the issue there,
so it's the best we can probably do.

NB: This causes that the traceroute command is now printed to the log
(as run_command() logs that by default), which we could also hide e.g.
through another parameter if wanted.

[0] https://bugzilla.proxmox.com/show_bug.cgi?id=4872
[1] https://forum.proxmox.com/threads/proxmox-installation-trying-to-detect-country.134301/

Signed-off-by: Christoph Heiss <c.heiss@proxmox.com>
---
Changes since v1:
  * use new CMD_FINISHED constant

 Proxmox/Install/RunEnv.pm | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/Proxmox/Install/RunEnv.pm b/Proxmox/Install/RunEnv.pm
index c393f67..d7ccea6 100644
--- a/Proxmox/Install/RunEnv.pm
+++ b/Proxmox/Install/RunEnv.pm
@@ -7,6 +7,7 @@ use Carp;
 use JSON qw(from_json to_json);

 use Proxmox::Log;
+use Proxmox::Sys::Command qw(run_command CMD_FINISHED);
 use Proxmox::Sys::File qw(file_read_firstline);
 use Proxmox::Sys::Block;
 use Proxmox::Sys::Net;
@@ -188,35 +189,36 @@ my sub detect_country_tracing_to : prototype($$) {
     my ($ipver, $destination) = @_;

     print STDERR "trying to detect country...\n";
-    open(my $TRACEROUTE_FH, '-|', 'traceroute', "-$ipver", '-N', '1', '-q', '1', '-n', $destination)
-	or return undef;

+    my $traceroute_cmd = ['traceroute', "-$ipver", '-N', '1', '-q', '1', '-n', $destination];
     my $geoip_bin = ($ipver == 6) ? 'geoiplookup6' : 'geoiplookup';

     my $country;
-
-    my $previous_alarm = alarm (10);
+    my $previous_alarm;
     eval {
 	local $SIG{ALRM} = sub { die "timed out!\n" };
-	my $line;
-	while (defined ($line = <$TRACEROUTE_FH>)) {
+	$previous_alarm = alarm (10);
+
+	run_command($traceroute_cmd, sub {
+	    my $line = shift;
+
 	    log_debug("DC TRACEROUTE: $line");
 	    if ($line =~ m/^\s*\d+\s+(\S+)\s/) {
 		my $geoip = qx/$geoip_bin $1/;
 		log_debug("DC GEOIP: $geoip");
+
 		if ($geoip =~ m/GeoIP Country Edition:\s*([A-Z]+),/) {
 		    $country = lc ($1);
 		    log_info("DC FOUND: $country\n");
-		    last;
+		    return CMD_FINISHED;
 		}
 	    }
-	}
+	}, undef, undef, 1);
+
     };
     my $err = $@;
     alarm ($previous_alarm);

-    close($TRACEROUTE_FH);
-
     if ($err) {
 	die "unable to detect country - $err\n";
     } elsif ($country) {
--
2.43.0





  parent reply	other threads:[~2024-02-13 15:14 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-13 15:13 [pve-devel] [PATCH installer v2 0/6] fix #4872: properly timeout `traceroute` command in " Christoph Heiss
2024-02-13 15:13 ` [pve-devel] [PATCH installer v2 1/6] low-level: initialize UI backend for 'dump-env' subcommand too Christoph Heiss
2024-02-13 15:13 ` [pve-devel] [PATCH installer v2 2/6] sys: command: factor out kill() + waitpid() from run_command() Christoph Heiss
2024-02-13 15:14 ` [pve-devel] [PATCH installer v2 3/6] sys: command: handle EINTR in run_command() Christoph Heiss
2024-02-13 15:14 ` [pve-devel] [PATCH installer v2 4/6] sys: command: allow terminating the process early from log subroutine Christoph Heiss
2024-02-13 15:14 ` [pve-devel] [PATCH installer v2 5/6] sys: command: add option to not print process output to stdout Christoph Heiss
2024-02-13 15:14 ` Christoph Heiss [this message]
2024-02-23 15:17 ` [pve-devel] applied-esries: [PATCH installer v2 0/6] fix #4872: properly timeout `traceroute` command in country detection Thomas Lamprecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240213151405.1282639-7-c.heiss@proxmox.com \
    --to=c.heiss@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal