Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0bdf6d6

Browse files
committed
Test both 0.0.0.0 and 127.0.0.x addresses to find a usable port.
Commit c098509 changed PostgresNode::get_new_node() to probe 0.0.0.0 instead of 127.0.0.1, but the new test was less effective for Windows native Perl. This increased the failure rate of buildfarm members bowerbird and jacana. Instead, test 0.0.0.0 and concrete addresses. This restores the old level of defense, but the algorithm is still subject to its longstanding time of check to time of use race condition. Back-patch to 9.6, like the previous change. Discussion: https://postgr.es/m/GrdLgAdUK9FdyZg8VIcTDKVOkys122ZINEb3CjjoySfGj2KyPiMKTh1zqtRp0TAD7FJ27G-OBB3eplxIB5GhcQH5o8zzGZfp0MuJaXJxVxk=@yesql.se
1 parent 31e2caa commit 0bdf6d6

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

src/test/perl/PostgresNode.pm

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,27 +1030,30 @@ sub get_new_node
10301030
$found = 0 if ($node->port == $port);
10311031
}
10321032

1033-
# Check to see if anything else is listening on this TCP port. Accept
1034-
# only ports available for all possible listen_addresses values, so
1035-
# the caller can harness this port for the widest range of purposes.
1036-
# This is *necessary* on Windows, and seems like a good idea on Unixen
1037-
# as well, even though we don't ask the postmaster to open a TCP port
1038-
# on Unix.
1033+
# Check to see if anything else is listening on this TCP port. This
1034+
# is *necessary* on $use_tcp (Windows) configurations. Seek a port
1035+
# available for all possible listen_addresses values, for own_host
1036+
# nodes and so the caller can harness this port for the widest range
1037+
# of purposes. The 0.0.0.0 test achieves that for post-2006 Cygwin,
1038+
# which automatically sets SO_EXCLUSIVEADDRUSE. The same holds for
1039+
# MSYS (a Cygwin fork). Testing 0.0.0.0 is insufficient for Windows
1040+
# native Perl (https://stackoverflow.com/a/14388707), so we also test
1041+
# individual addresses.
1042+
#
1043+
# This seems like a good idea on Unixen as well, even though we don't
1044+
# ask the postmaster to open a TCP port on Unix. On Non-Linux,
1045+
# non-Windows kernels, binding to 127.0.0.1/24 addresses other than
1046+
# 127.0.0.1 fails with EADDRNOTAVAIL.
1047+
#
1048+
# XXX A port available now may become unavailable by the time we start
1049+
# the postmaster.
10391050
if ($found == 1)
10401051
{
1041-
my $iaddr = inet_aton('0.0.0.0');
1042-
my $paddr = sockaddr_in($port, $iaddr);
1043-
my $proto = getprotobyname("tcp");
1044-
1045-
socket(SOCK, PF_INET, SOCK_STREAM, $proto)
1046-
or die "socket failed: $!";
1047-
1048-
# As in postmaster, don't use SO_REUSEADDR on Windows
1049-
setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
1050-
unless $TestLib::windows_os;
1051-
(bind(SOCK, $paddr) && listen(SOCK, SOMAXCONN))
1052-
or $found = 0;
1053-
close(SOCK);
1052+
foreach my $addr (qw(127.0.0.1 0.0.0.0),
1053+
$use_tcp ? qw(127.0.0.2 127.0.0.3) : ())
1054+
{
1055+
can_bind($addr, $port) or $found = 0;
1056+
}
10541057
}
10551058
}
10561059

@@ -1062,8 +1065,6 @@ sub get_new_node
10621065
{
10631066
if ($use_tcp)
10641067
{
1065-
# This assumes $use_tcp platforms treat every address in
1066-
# 127.0.0.1/24, not just 127.0.0.1, as a usable loopback.
10671068
$last_host_assigned++;
10681069
$last_host_assigned > 254 and BAIL_OUT("too many own_host nodes");
10691070
$host = '127.0.0.' . $last_host_assigned;
@@ -1087,6 +1088,25 @@ sub get_new_node
10871088
return $node;
10881089
}
10891090

1091+
# Internal routine to check whether a host:port is available to bind
1092+
sub can_bind
1093+
{
1094+
my ($host, $port) = @_;
1095+
my $iaddr = inet_aton($host);
1096+
my $paddr = sockaddr_in($port, $iaddr);
1097+
my $proto = getprotobyname("tcp");
1098+
1099+
socket(SOCK, PF_INET, SOCK_STREAM, $proto)
1100+
or die "socket failed: $!";
1101+
1102+
# As in postmaster, don't use SO_REUSEADDR on Windows
1103+
setsockopt(SOCK, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
1104+
unless $TestLib::windows_os;
1105+
my $ret = bind(SOCK, $paddr) && listen(SOCK, SOMAXCONN);
1106+
close(SOCK);
1107+
return $ret;
1108+
}
1109+
10901110
# Retain the errno on die() if set, else assume a generic errno of 1.
10911111
# This will instruct the END handler on how to handle artifacts left
10921112
# behind from tests.

0 commit comments

Comments
 (0)