diff --git a/src/test/perl/PostgresNode.pm b/src/test/perl/PostgresNode.pm index e42c117..1f38640 100644 --- a/src/test/perl/PostgresNode.pm +++ b/src/test/perl/PostgresNode.pm @@ -90,6 +90,7 @@ use File::Spec; use File::Temp (); use IPC::Run; use RecursiveCopy; +use Socket; use Test::More; use TestLib (); use Scalar::Util qw(blessed); @@ -842,16 +843,32 @@ sub get_new_node # wrap correctly around range end $port = 49152 if ++$port >= 65536; print "# Checking for port $port\n"; - if (!TestLib::run_log([ 'pg_isready', '-p', $port ])) + $found = 1; + + # Found a potential candidate port number. Check first that it is + # not included in the list of registered nodes. + foreach my $node (@all_nodes) { - $found = 1; + $found = 0 if ($node->port == $port); + } - # Found a potential candidate port number. Check first that it is - # not included in the list of registered nodes. - foreach my $node (@all_nodes) - { - $found = 0 if ($node->port == $port); - } + # On non-Windows, port unicity is ensured by the unique Unix socket + # directory where all the nodes registered in a given test are + # listening, and this directory is different for each test. On + # Windows though, all the nodes registered in a test are listening + # to localhost, other PostgreSQL instances running on a server as + # well as anything else listening to a port may cause failures, + # so check if a given port is already listening to TCP connections + # before deciding if it can safely be used or not. + if ($found == 1 && $TestLib::windows_os) + { + my $iaddr = inet_aton($ENV{PGHOST}); + my $paddr = sockaddr_in("$port", $iaddr); + my $proto = getprotobyname("tcp"); + + socket(SOCK, PF_INET, SOCK_STREAM, $proto) or die; + $found = 0 if connect(SOCK, $paddr); + close(SOCK); } }