* [pve-devel] [PATCH installer 0/4] fix #4872: properly timeout `traceroute` command in coutry detection @ 2024-02-09 10:55 Christoph Heiss 2024-02-09 10:55 ` [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too Christoph Heiss ` (3 more replies) 0 siblings, 4 replies; 9+ messages in thread From: Christoph Heiss @ 2024-02-09 10:55 UTC (permalink / raw) To: pve-devel For all the details, see patch #4. TL;DR: SIGALRM does not interrupt line reading using <>, causing the installer to hang on country detection. Fix it by using Proxmox::Sys::Command::run_command(), which properly interacts with SIGALRM. Patch #1 is a rather mundane fix for some niche cases, #2 and #3 are simply preparatory and to not alter existing behaviour. Christoph Heiss (4): low-level: initialize UI backend for 'dump-env' subcommand too sys: command: allow terminating the process early from log subroutine sys: command: add option to not print process output to stdout fix #4872: run env: use run_command() for country detection Proxmox/Install/RunEnv.pm | 23 ++++++++++++----------- Proxmox/Sys/Command.pm | 13 ++++++++++--- proxmox-low-level-installer | 1 + 3 files changed, 23 insertions(+), 14 deletions(-) -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too 2024-02-09 10:55 [pve-devel] [PATCH installer 0/4] fix #4872: properly timeout `traceroute` command in coutry detection Christoph Heiss @ 2024-02-09 10:55 ` Christoph Heiss 2024-02-09 12:36 ` Aaron Lauterer 2024-02-09 10:55 ` [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine Christoph Heiss ` (2 subsequent siblings) 3 siblings, 1 reply; 9+ messages in thread From: Christoph Heiss @ 2024-02-09 10:55 UTC (permalink / raw) To: pve-devel Some detection routines might try to log things and call some Proxmox::Ui functions all the way down, so just initialize it with the stdio backend to avoid errors. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> --- proxmox-low-level-installer | 1 + 1 file changed, 1 insertion(+) diff --git a/proxmox-low-level-installer b/proxmox-low-level-installer index d127a40..2848295 100755 --- a/proxmox-low-level-installer +++ b/proxmox-low-level-installer @@ -91,6 +91,7 @@ Proxmox::Log::init("/tmp/install-low-level-${cmd}.log"); my $env = Proxmox::Install::ISOEnv::get(); if ($cmd eq 'dump-env') { + Proxmox::UI::init_stdio({}, $env); my $out_dir = $env->{locations}->{run}; make_path($out_dir); -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too 2024-02-09 10:55 ` [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too Christoph Heiss @ 2024-02-09 12:36 ` Aaron Lauterer 2024-02-12 10:15 ` Christoph Heiss 0 siblings, 1 reply; 9+ messages in thread From: Aaron Lauterer @ 2024-02-09 12:36 UTC (permalink / raw) To: Proxmox VE development discussion, Christoph Heiss Is this something I should consider for the new dump-udev subcommand as well? https://lists.proxmox.com/pipermail/pve-devel/2024-January/061433.html On 2/9/24 11:55, Christoph Heiss wrote: > Some detection routines might try to log things and call some > Proxmox::Ui functions all the way down, so just initialize it with the > stdio backend to avoid errors. > > Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> > --- > proxmox-low-level-installer | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/proxmox-low-level-installer b/proxmox-low-level-installer > index d127a40..2848295 100755 > --- a/proxmox-low-level-installer > +++ b/proxmox-low-level-installer > @@ -91,6 +91,7 @@ Proxmox::Log::init("/tmp/install-low-level-${cmd}.log"); > > my $env = Proxmox::Install::ISOEnv::get(); > if ($cmd eq 'dump-env') { > + Proxmox::UI::init_stdio({}, $env); > > my $out_dir = $env->{locations}->{run}; > make_path($out_dir); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too 2024-02-09 12:36 ` Aaron Lauterer @ 2024-02-12 10:15 ` Christoph Heiss 0 siblings, 0 replies; 9+ messages in thread From: Christoph Heiss @ 2024-02-12 10:15 UTC (permalink / raw) To: Aaron Lauterer; +Cc: Proxmox VE development discussion On Fri, Feb 09, 2024 at 01:36:12PM +0100, Aaron Lauterer wrote: > Is this something I should consider for the new dump-udev subcommand as well? > > https://lists.proxmox.com/pipermail/pve-devel/2024-January/061433.html As it also calls deeper into the installer code, I'd say yes. Although nothing ever calls UI code on that chain, better future-proof it now :^) > > On 2/9/24 11:55, Christoph Heiss wrote: > > Some detection routines might try to log things and call some > > Proxmox::Ui functions all the way down, so just initialize it with the > > stdio backend to avoid errors. > > > > Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> > > --- > > proxmox-low-level-installer | 1 + > > 1 file changed, 1 insertion(+) > > > > diff --git a/proxmox-low-level-installer b/proxmox-low-level-installer > > index d127a40..2848295 100755 > > --- a/proxmox-low-level-installer > > +++ b/proxmox-low-level-installer > > @@ -91,6 +91,7 @@ Proxmox::Log::init("/tmp/install-low-level-${cmd}.log"); > > my $env = Proxmox::Install::ISOEnv::get(); > > if ($cmd eq 'dump-env') { > > + Proxmox::UI::init_stdio({}, $env); > > my $out_dir = $env->{locations}->{run}; > > make_path($out_dir); ^ permalink raw reply [flat|nested] 9+ messages in thread
* [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine 2024-02-09 10:55 [pve-devel] [PATCH installer 0/4] fix #4872: properly timeout `traceroute` command in coutry detection Christoph Heiss 2024-02-09 10:55 ` [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too Christoph Heiss @ 2024-02-09 10:55 ` Christoph Heiss 2024-02-12 10:58 ` Thomas Lamprecht 2024-02-09 10:56 ` [pve-devel] [PATCH installer 3/4] sys: command: add option to not print process output to stdout Christoph Heiss 2024-02-09 10:56 ` [pve-devel] [PATCH installer 4/4] fix #4872: run env: use run_command() for country detection Christoph Heiss 3 siblings, 1 reply; 9+ messages in thread From: Christoph Heiss @ 2024-02-09 10:55 UTC (permalink / raw) To: pve-devel This is done in a entirely backwards-compatible way, i.e. existing usages don't need any modification. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> --- Proxmox/Sys/Command.pm | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Proxmox/Sys/Command.pm b/Proxmox/Sys/Command.pm index c3e24b3..bf67b27 100644 --- a/Proxmox/Sys/Command.pm +++ b/Proxmox/Sys/Command.pm @@ -114,7 +114,14 @@ sub run_command { $logout .= $buf; while ($logout =~ s/^([^\010\r\n]*)(\r|\n|(\010)+|\r\n)//s) { my $line = $1; - $func->($line) if $func; + if ($func) { + my $ret = $func->($line); + if (defined($ret) && $ret == 1) { + kill('KILL', $pid); + waitpid($pid, 0); + return $ostream; + } + }; } } elsif ($h eq $error) { -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine 2024-02-09 10:55 ` [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine Christoph Heiss @ 2024-02-12 10:58 ` Thomas Lamprecht 2024-02-12 12:06 ` Christoph Heiss 0 siblings, 1 reply; 9+ messages in thread From: Thomas Lamprecht @ 2024-02-12 10:58 UTC (permalink / raw) To: Proxmox VE development discussion, Christoph Heiss Am 09/02/2024 um 11:55 schrieb Christoph Heiss: > This is done in a entirely backwards-compatible way, i.e. existing > usages don't need any modification. can you actually describe here that you do so by checking the return value of the stdout parser closure, can be done in a short sentence and surely doesn't hurt. > > Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> > --- > Proxmox/Sys/Command.pm | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/Proxmox/Sys/Command.pm b/Proxmox/Sys/Command.pm > index c3e24b3..bf67b27 100644 > --- a/Proxmox/Sys/Command.pm > +++ b/Proxmox/Sys/Command.pm > @@ -114,7 +114,14 @@ sub run_command { > $logout .= $buf; > while ($logout =~ s/^([^\010\r\n]*)(\r|\n|(\010)+|\r\n)//s) { > my $line = $1; > - $func->($line) if $func; > + if ($func) { > + my $ret = $func->($line); > + if (defined($ret) && $ret == 1) { maybe we can define a constant for this, so that we have descriptive name that better conveys the meaning of this special return value, e.g., something like: use constant RET_TIMED_OUT => 1; (no hard feelings on that name, just used the first thing that came to my mind) > + kill('KILL', $pid); > + waitpid($pid, 0); FWIW, this can block forever too though? How about factoring out the kill+waiting in it's own sub (could be also one for waitpid with timeout and combined kill+waitpid that reuses the first one), that does a TERM first, checks with WNOHANG if the target PID exited and if not, sends the KILL and loops until a timeout (say, /throws dice/, 5s) expired. That way no D-state, or whatever else can block the process' death, is hanging up the installer. > + return $ostream; > + } > + }; > } > > } elsif ($h eq $error) { ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine 2024-02-12 10:58 ` Thomas Lamprecht @ 2024-02-12 12:06 ` Christoph Heiss 0 siblings, 0 replies; 9+ messages in thread From: Christoph Heiss @ 2024-02-12 12:06 UTC (permalink / raw) To: Thomas Lamprecht; +Cc: Proxmox VE development discussion Thanks for the review! On Mon, Feb 12, 2024 at 11:58:27AM +0100, Thomas Lamprecht wrote: > Am 09/02/2024 um 11:55 schrieb Christoph Heiss: > > This is done in a entirely backwards-compatible way, i.e. existing > > usages don't need any modification. > > can you actually describe here that you do so by checking the return > value of the stdout parser closure, can be done in a short sentence > and surely doesn't hurt. I'll add some more documentation for this in v2. > > > > > Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> > > --- > > Proxmox/Sys/Command.pm | 9 ++++++++- > > 1 file changed, 8 insertions(+), 1 deletion(-) > > > > diff --git a/Proxmox/Sys/Command.pm b/Proxmox/Sys/Command.pm > > index c3e24b3..bf67b27 100644 > > --- a/Proxmox/Sys/Command.pm > > +++ b/Proxmox/Sys/Command.pm > > @@ -114,7 +114,14 @@ sub run_command { > > $logout .= $buf; > > while ($logout =~ s/^([^\010\r\n]*)(\r|\n|(\010)+|\r\n)//s) { > > my $line = $1; > > - $func->($line) if $func; > > + if ($func) { > > + my $ret = $func->($line); > > + if (defined($ret) && $ret == 1) { > > maybe we can define a constant for this, so that we have > descriptive name that better conveys the meaning of this special > return value, e.g., something like: Sounds good, I will add that. > > use constant RET_TIMED_OUT => 1; > > (no hard feelings on that name, just used the first thing that came to > my mind) > > > > + kill('KILL', $pid); > > + waitpid($pid, 0); > > FWIW, this can block forever too though? It /could/ probably happen if the process e.g. somehow enters D-state after reading the previous line of output, good catch. > > How about factoring out the kill+waiting in it's own sub (could be > also one for waitpid with timeout and combined kill+waitpid that reuses > the first one), that does a TERM first, checks with WNOHANG if the > target PID exited and if not, sends the KILL and loops until a timeout > (say, /throws dice/, 5s) expired. > > That way no D-state, or whatever else can block the process' death, > is hanging up the installer. That seems like the /really/ bulletproof way. This was more a proof-of-concept-fix anyway in the beginning, so a bit of refactoring on that thing is warranted after all, I guess. > > > + return $ostream; > > + } > > + }; > > } > > > > } elsif ($h eq $error) { > ^ permalink raw reply [flat|nested] 9+ messages in thread
* [pve-devel] [PATCH installer 3/4] sys: command: add option to not print process output to stdout 2024-02-09 10:55 [pve-devel] [PATCH installer 0/4] fix #4872: properly timeout `traceroute` command in coutry detection Christoph Heiss 2024-02-09 10:55 ` [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too Christoph Heiss 2024-02-09 10:55 ` [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine Christoph Heiss @ 2024-02-09 10:56 ` Christoph Heiss 2024-02-09 10:56 ` [pve-devel] [PATCH installer 4/4] fix #4872: run env: use run_command() for country detection Christoph Heiss 3 siblings, 0 replies; 9+ messages in thread From: Christoph Heiss @ 2024-02-09 10:56 UTC (permalink / raw) To: pve-devel Fully backwards-compatible again, only takes effect if the new argument is actually specified. Signed-off-by: Christoph Heiss <c.heiss@proxmox.com> --- Proxmox/Sys/Command.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Proxmox/Sys/Command.pm b/Proxmox/Sys/Command.pm index bf67b27..a5129fd 100644 --- a/Proxmox/Sys/Command.pm +++ b/Proxmox/Sys/Command.pm @@ -40,7 +40,7 @@ sub syscmd { } sub run_command { - my ($cmd, $func, $input, $noout) = @_; + my ($cmd, $func, $input, $noout, $noprint) = @_; my $cmdstr; if (!ref($cmd)) { @@ -127,7 +127,7 @@ sub run_command { } elsif ($h eq $error) { $ostream .= $buf if !($noout || $func); } - print $buf; + print $buf if !$noprint; STDOUT->flush(); log_info($buf); } -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [pve-devel] [PATCH installer 4/4] fix #4872: run env: use run_command() for country detection 2024-02-09 10:55 [pve-devel] [PATCH installer 0/4] fix #4872: properly timeout `traceroute` command in coutry detection Christoph Heiss ` (2 preceding siblings ...) 2024-02-09 10:56 ` [pve-devel] [PATCH installer 3/4] sys: command: add option to not print process output to stdout Christoph Heiss @ 2024-02-09 10:56 ` Christoph Heiss 3 siblings, 0 replies; 9+ messages in thread From: Christoph Heiss @ 2024-02-09 10:56 UTC (permalink / raw) To: pve-devel 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 { "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> --- Proxmox/Install/RunEnv.pm | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Proxmox/Install/RunEnv.pm b/Proxmox/Install/RunEnv.pm index c393f67..ee6b8bc 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); use Proxmox::Sys::File qw(file_read_firstline); use Proxmox::Sys::Block; use Proxmox::Sys::Net; @@ -188,34 +189,34 @@ 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); eval { local $SIG{ALRM} = sub { die "timed out!\n" }; - my $line; - while (defined ($line = <$TRACEROUTE_FH>)) { + my $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 1; } } - } + }, undef, undef, 1); + + alarm ($previous_alarm); }; my $err = $@; - alarm ($previous_alarm); - - close($TRACEROUTE_FH); if ($err) { die "unable to detect country - $err\n"; -- 2.43.0 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2024-02-12 12:06 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2024-02-09 10:55 [pve-devel] [PATCH installer 0/4] fix #4872: properly timeout `traceroute` command in coutry detection Christoph Heiss 2024-02-09 10:55 ` [pve-devel] [PATCH installer 1/4] low-level: initialize UI backend for 'dump-env' subcommand too Christoph Heiss 2024-02-09 12:36 ` Aaron Lauterer 2024-02-12 10:15 ` Christoph Heiss 2024-02-09 10:55 ` [pve-devel] [PATCH installer 2/4] sys: command: allow terminating the process early from log subroutine Christoph Heiss 2024-02-12 10:58 ` Thomas Lamprecht 2024-02-12 12:06 ` Christoph Heiss 2024-02-09 10:56 ` [pve-devel] [PATCH installer 3/4] sys: command: add option to not print process output to stdout Christoph Heiss 2024-02-09 10:56 ` [pve-devel] [PATCH installer 4/4] fix #4872: run env: use run_command() for country detection Christoph Heiss
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.