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

Attachment: pgpdPaKNRisoF.pgp
Description: PGP signature

Reply via email to