@ -1088,27 +1088,30 @@ sub get_new_node
$ found = 0 if ( $ node - > port == $ port ) ;
}
# Check to see if anything else is listening on this TCP port. Accept
# only ports available for all possible listen_addresses values, so
# the caller can harness this port for the widest range of purposes.
# This is *necessary* on Windows, and seems like a good idea on Unixen
# as well, even though we don't ask the postmaster to open a TCP port
# on Unix.
# Check to see if anything else is listening on this TCP port. This
# is *necessary* on $use_tcp (Windows) configurations. Seek a port
# available for all possible listen_addresses values, for own_host
# nodes and so the caller can harness this port for the widest range
# of purposes. The 0.0.0.0 test achieves that for post-2006 Cygwin,
# which automatically sets SO_EXCLUSIVEADDRUSE. The same holds for
# MSYS (a Cygwin fork). Testing 0.0.0.0 is insufficient for Windows
# native Perl (https://stackoverflow.com/a/14388707), so we also test
# individual addresses.
#
# This seems like a good idea on Unixen as well, even though we don't
# ask the postmaster to open a TCP port on Unix. On Non-Linux,
# non-Windows kernels, binding to 127.0.0.1/24 addresses other than
# 127.0.0.1 fails with EADDRNOTAVAIL.
#
# XXX A port available now may become unavailable by the time we start
# the postmaster.
if ( $ found == 1 )
{
my $ iaddr = inet_aton ( '0.0.0.0' ) ;
my $ paddr = sockaddr_in ( $ port , $ iaddr ) ;
my $ proto = getprotobyname ( "tcp" ) ;
socket ( SOCK , PF_INET , SOCK_STREAM , $ proto )
or die "socket failed: $!" ;
# As in postmaster, don't use SO_REUSEADDR on Windows
setsockopt ( SOCK , SOL_SOCKET , SO_REUSEADDR , pack ( "l" , 1 ) )
unless $ TestLib:: windows_os ;
( bind ( SOCK , $ paddr ) && listen ( SOCK , SOMAXCONN ) )
or $ found = 0 ;
close ( SOCK ) ;
foreach my $ addr ( qw( 127.0.0.1 0.0.0.0 ) ,
$ use_tcp ? qw( 127.0.0.2 127.0.0.3 ) : ( ) )
{
can_bind ( $ addr , $ port ) or $ found = 0 ;
}
}
}
@ -1120,8 +1123,6 @@ sub get_new_node
{
if ( $ use_tcp )
{
# This assumes $use_tcp platforms treat every address in
# 127.0.0.1/24, not just 127.0.0.1, as a usable loopback.
$ last_host_assigned + + ;
$ last_host_assigned > 254 and BAIL_OUT ( "too many own_host nodes" ) ;
$ host = '127.0.0.' . $ last_host_assigned ;
@ -1145,6 +1146,25 @@ sub get_new_node
return $ node ;
}
# Internal routine to check whether a host:port is available to bind
sub can_bind
{
my ( $ host , $ port ) = @ _ ;
my $ iaddr = inet_aton ( $ host ) ;
my $ paddr = sockaddr_in ( $ port , $ iaddr ) ;
my $ proto = getprotobyname ( "tcp" ) ;
socket ( SOCK , PF_INET , SOCK_STREAM , $ proto )
or die "socket failed: $!" ;
# As in postmaster, don't use SO_REUSEADDR on Windows
setsockopt ( SOCK , SOL_SOCKET , SO_REUSEADDR , pack ( "l" , 1 ) )
unless $ TestLib:: windows_os ;
my $ ret = bind ( SOCK , $ paddr ) && listen ( SOCK , SOMAXCONN ) ;
close ( SOCK ) ;
return $ ret ;
}
# Retain the errno on die() if set, else assume a generic errno of 1.
# This will instruct the END handler on how to handle artifacts left
# behind from tests.