From 9a41a7b7c934cf62e819d00c2b6c2fc5c3add27b Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Tue, 27 Jun 2017 11:12:04 +0200 Subject: [PATCH] use more reliable checks in wait_for_vnc_port MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit We run into problems where this method returned to early, even if the port wasn't actually ready yet. The reason for this is that we checked /proc/net/tcp which does not guarantees and always up to date state of only those ports which are actuall available, i.e. a port could linger around (time-wait state) or appear even if it wasn't accepting connections yet (as stated in the kernel docs: /proc/net/tcp is seen as obsolete by the kernel devs). Use the `ss` tool from the iproute2 package, it uses netlink to get the current state and has switches where we can direct it to really only get the state of those sockets which interest us currently. I.e., we tell it to get only listening TCP sockets from the requested port. The only drawback is that we loop on a run_command, which is slower than just reading a file. A single loop needs about 1ms here vs the 60µs on the /proc/net/tcp read. But this isn't a api call which is used highly frequently but rather once per noVNC console open. Signed-off-by: Thomas Lamprecht --- src/PVE/Tools.pm | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/PVE/Tools.pm b/src/PVE/Tools.pm index da7da5d..f9ca118 100644 --- a/src/PVE/Tools.pm +++ b/src/PVE/Tools.pm @@ -739,18 +739,16 @@ sub wait_for_vnc_port { my $starttime = [gettimeofday]; my $elapsed; + my $found; while (($elapsed = tv_interval($starttime)) < $timeout) { - if (my $fh = IO::File->new ("/proc/net/tcp", "r")) { - while (defined (my $line = <$fh>)) { - if ($line =~ m/^\s*\d+:\s+([0-9A-Fa-f]{8}):([0-9A-Fa-f]{4})\s/) { - if ($port == hex($2)) { - close($fh); - return 1; - } - } + # -Htln = don't print header, tcp, listening sockets only, numeric ports + run_command(['/bin/ss', '-Htln', "sport = :$port"], outfunc => sub { + my $line = shift; + if ($line =~ m/^LISTEN\s+\d+\s+\d+\s+\S+:(\d+)\s/) { + $found = 1 if ($port == $1); } - close($fh); - } + }); + return 1 if $found; $sleeptime += 100000 if $sleeptime < 1000000; usleep($sleeptime); } -- 2.39.2