tags 624500 + patch thanks Thanks to intrigeri's very helpful investigation and explanation, I sorted out what is going on with Net::Server when it uses a dynamically-assigned port and undergoes a HUP.
The test for socket reconnection fails because the server knows it
initially requested port 0, but the actual socket has the OS-assigned
port associated with it. So Net::Server compares the intended/requested
hup_string (e.g. "*|0|TCP") against the already-bound socket's hup_string
(e.g. "*|32633|TCP") and decides that they don't match.
The fix is to look at the already-bound hup_string and construct what it
would look like had it been the result of a dynamic request (replace the
port number with 0), and accept that as a match against the requested
hup_string as well.
Also, to ensure that NS_port is set properly after a HUP when using
dynamic port allocation, we propagate that info in
Net::Server::Proto::TCP->reconnect() in the same way it is propagated in
Net::Server::Proto::TCP->connect().
This appears to resolve the issue.
--dkg
diff --git a/lib/Net/Server.pm b/lib/Net/Server.pm
index 4c5e8d9..31f2cdf 100644
--- a/lib/Net/Server.pm
+++ b/lib/Net/Server.pm
@@ -419,8 +419,15 @@ sub bind {
foreach my $info (split /\n/, $ENV{BOUND_SOCKETS}) {
my ($fd, $hup_string) = split /\|/, $info, 2;
$fd = ($fd =~ /^(\d+)$/) ? $1 : $self->fatal("Bad file descriptor");
+
+ # if our config wants port 0 (dynamically-allocated port from
+ # the OS), we want to make sure we can reconnect to those.
+ my $dynamic_hup_string = $hup_string;
+ $dynamic_hup_string =~ s/\|\d+\|/|0|/;
+
foreach my $sock ( @{ $prop->{sock} } ){
- if ($hup_string eq $sock->hup_string) {
+ if (($hup_string eq $sock->hup_string) or
+ ($dynamic_hup_string eq $sock->hup_string)) {
$sock->log_connect($self);
$sock->reconnect($fd, $self);
last;
diff --git a/lib/Net/Server/Proto/TCP.pm b/lib/Net/Server/Proto/TCP.pm
index 437f5d4..df7221c 100644
--- a/lib/Net/Server/Proto/TCP.pm
+++ b/lib/Net/Server/Proto/TCP.pm
@@ -104,9 +104,16 @@ sub reconnect {
my $fd = shift;
my $server = shift;
+ my $port = $sock->NS_port;
+
$sock->fdopen( $fd, 'w' )
or $server->fatal("Error opening to file descriptor ($fd) [$!]");
+ if ($port == 0 && ($port = $sock->sockport)) {
+ $sock->NS_port($port);
+ $server->log(2,"Bound to auto-assigned port $port");
+ }
+
}
### allow for endowing the child
pgpdPaKNRisoF.pgp
Description: PGP signature

