Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit45d6789

Browse files
committed
Avoid picking already-bound TCP ports in kerberos and ldap test suites.
src/test/kerberos and src/test/ldap need to run a private authenticationserver of the relevant type, for which they need a free TCP port.They were just picking a random port number in 48K-64K, which worksexcept when something's already using the particular port. Notably,the probability of failure rises dramatically if one simply runs thosetests in a tight loop, because each test cycle leaves behind a bunch ofhigh ports that are transiently in TIME_WAIT state.To fix, split out the code that PostgresNode.pm already had foridentifying a free TCP port number, so that it can be invoked to choosea port for the KDC or LDAP server. This isn't 100% bulletproof, sinceconceivably something else on the machine could grab the port betweenthe time we check and the time we actually start the server. But that'sa pretty short window, so in practice this should be good enough.Back-patch to v11 where these test suites were added.Patch by me, reviewed by Andrew Dunstan.Discussion:https://postgr.es/m/3397.1564872168@sss.pgh.pa.us
1 parente3967a1 commit45d6789

File tree

3 files changed

+86
-48
lines changed

3 files changed

+86
-48
lines changed

‎src/test/kerberos/t/001_auth.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
my$kdc_conf ="${TestLib::tmp_check}/kdc.conf";
5757
my$krb5_log ="${TestLib::tmp_check}/krb5libs.log";
5858
my$kdc_log ="${TestLib::tmp_check}/krb5kdc.log";
59-
my$kdc_port =int(rand() * 16384) + 49152;
59+
my$kdc_port =get_free_port();
6060
my$kdc_datadir ="${TestLib::tmp_check}/krb5kdc";
6161
my$kdc_pidfile ="${TestLib::tmp_check}/krb5kdc.pid";
6262
my$keytab ="${TestLib::tmp_check}/krb5.keytab";

‎src/test/ldap/t/001_auth.pl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
my$slapd_logfile ="${TestLib::tmp_check}/slapd.log";
4949
my$ldap_conf ="${TestLib::tmp_check}/ldap.conf";
5050
my$ldap_server ='localhost';
51-
my$ldap_port =int(rand() * 16384) + 49152;
51+
my$ldap_port =get_free_port();
5252
my$ldaps_port =$ldap_port + 1;
5353
my$ldap_url ="ldap://$ldap_server:$ldap_port";
5454
my$ldaps_url ="ldaps://$ldap_server:$ldaps_port";

‎src/test/perl/PostgresNode.pm

Lines changed: 84 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ PostgresNode - class representing PostgreSQL server instance
6363
# Stop the server
6464
$node->stop('fast');
6565
66+
# Find a free, unprivileged TCP port to bind some other service to
67+
my $port = get_free_port();
68+
6669
=head1DESCRIPTION
6770
6871
PostgresNode contains a set of routines able to work on a PostgreSQL node,
@@ -102,6 +105,7 @@ use Scalar::Util qw(blessed);
102105

103106
our@EXPORT =qw(
104107
get_new_node
108+
get_free_port
105109
);
106110

107111
our ($use_tcp,$test_localhost,$test_pghost,$last_host_assigned,
@@ -1022,9 +1026,68 @@ sub get_new_node
10221026
my$class ='PostgresNode';
10231027
$class =shiftifscalar(@_) % 2 != 1;
10241028
my ($name,%params) =@_;
1025-
my$port_is_forced =defined$params{port};
1026-
my$found =$port_is_forced;
1027-
my$port =$port_is_forced ?$params{port} :$last_port_assigned;
1029+
1030+
# Select a port.
1031+
my$port;
1032+
if (defined$params{port})
1033+
{
1034+
$port =$params{port};
1035+
}
1036+
else
1037+
{
1038+
# When selecting a port, we look for an unassigned TCP port number,
1039+
# even if we intend to use only Unix-domain sockets. This is clearly
1040+
# necessary on $use_tcp (Windows) configurations, and it seems like a
1041+
# good idea on Unixen as well.
1042+
$port = get_free_port();
1043+
}
1044+
1045+
# Select a host.
1046+
my$host =$test_pghost;
1047+
if ($params{own_host})
1048+
{
1049+
if ($use_tcp)
1050+
{
1051+
$last_host_assigned++;
1052+
$last_host_assigned > 254and BAIL_OUT("too many own_host nodes");
1053+
$host ='127.0.0.' .$last_host_assigned;
1054+
}
1055+
else
1056+
{
1057+
$host ="$test_pghost/$name";# Assume $name =~ /^[-_a-zA-Z0-9]+$/
1058+
mkdir$host;
1059+
}
1060+
}
1061+
1062+
# Lock port number found by creating a new node
1063+
my$node =$class->new($name,$host,$port);
1064+
1065+
# Add node to list of nodes
1066+
push(@all_nodes,$node);
1067+
1068+
return$node;
1069+
}
1070+
1071+
=pod
1072+
1073+
=itemget_free_port()
1074+
1075+
Locate an unprivileged (high) TCP port that's not currently bound to
1076+
anything. This is used by get_new_node, and is also exported for use
1077+
by test cases that need to start other, non-Postgres servers.
1078+
1079+
Ports assigned to existing PostgresNode objects are automatically
1080+
excluded, even if those servers are not currently running.
1081+
1082+
XXX A port available now may become unavailable by the time we start
1083+
the desired service.
1084+
1085+
=cut
1086+
1087+
subget_free_port
1088+
{
1089+
my$found = 0;
1090+
my$port =$last_port_assigned;
10281091

10291092
while ($found == 0)
10301093
{
@@ -1041,63 +1104,38 @@ sub get_new_node
10411104
$found = 0if ($node->port ==$port);
10421105
}
10431106

1044-
# Check to see if anything else is listening on this TCP port. This
1045-
# is *necessary* on $use_tcp (Windows) configurations. Seek a port
1046-
# available for all possible listen_addresses values, for own_host
1047-
# nodes and so the caller can harness this port for the widest range
1048-
# of purposes. The 0.0.0.0 test achieves that for post-2006 Cygwin,
1049-
# which automatically sets SO_EXCLUSIVEADDRUSE. The same holds for
1050-
# MSYS (a Cygwin fork). Testing 0.0.0.0 is insufficient for Windows
1051-
# native Perl (https://stackoverflow.com/a/14388707), so we also test
1107+
# Check to see if anything else is listening on this TCP port.
1108+
# Seek a port available for all possible listen_addresses values,
1109+
# so callers can harness this port for the widest range of purposes.
1110+
# The 0.0.0.0 test achieves that for post-2006 Cygwin, which
1111+
# automatically sets SO_EXCLUSIVEADDRUSE. The same holds for MSYS (a
1112+
# Cygwin fork). Testing 0.0.0.0 is insufficient for Windows native
1113+
# Perl (https://stackoverflow.com/a/14388707), so we also test
10521114
# individual addresses.
10531115
#
1054-
# This seems like a good idea on Unixen as well, even though we don't
1055-
# ask the postmaster to open a TCP port on Unix. On Non-Linux,
1056-
# non-Windows kernels, binding to 127.0.0.1/24 addresses other than
1057-
# 127.0.0.1 might fail with EADDRNOTAVAIL. Binding to 0.0.0.0 is
1058-
# unnecessary on non-Windows systems.
1059-
#
1060-
# XXX A port available now may become unavailable by the time we start
1061-
# the postmaster.
1116+
# On non-Linux, non-Windows kernels, binding to 127.0.0/24 addresses
1117+
# other than 127.0.0.1 might fail with EADDRNOTAVAIL. Binding to
1118+
# 0.0.0.0 is unnecessary on non-Windows systems.
10621119
if ($found == 1)
10631120
{
10641121
foreachmy$addr (qw(127.0.0.1),
10651122
$use_tcp ?qw(127.0.0.2 127.0.0.3 0.0.0.0) : ())
10661123
{
1067-
can_bind($addr,$port)or$found = 0;
1124+
if (!can_bind($addr,$port))
1125+
{
1126+
$found = 0;
1127+
last;
1128+
}
10681129
}
10691130
}
10701131
}
10711132

10721133
print"# Found port$port\n";
10731134

1074-
# Select a host.
1075-
my$host =$test_pghost;
1076-
if ($params{own_host})
1077-
{
1078-
if ($use_tcp)
1079-
{
1080-
$last_host_assigned++;
1081-
$last_host_assigned > 254and BAIL_OUT("too many own_host nodes");
1082-
$host ='127.0.0.' .$last_host_assigned;
1083-
}
1084-
else
1085-
{
1086-
$host ="$test_pghost/$name";# Assume $name =~ /^[-_a-zA-Z0-9]+$/
1087-
mkdir$host;
1088-
}
1089-
}
1090-
1091-
# Lock port number found by creating a new node
1092-
my$node =$class->new($name,$host,$port);
1093-
1094-
# Add node to list of nodes
1095-
push(@all_nodes,$node);
1135+
# Update port for next time
1136+
$last_port_assigned =$port;
10961137

1097-
# And update port for next time
1098-
$port_is_forcedor$last_port_assigned =$port;
1099-
1100-
return$node;
1138+
return$port;
11011139
}
11021140

11031141
# Internal routine to check whether a host:port is available to bind

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp