Bug#624500: Net::Server: analysis of the post-HUP auto-assigned port retrieval bug

intrigeri intrigeri+debian at boum.org
Sun Nov 6 10:19:05 UTC 2011


found 624500 0.99-2
thanks

Hi,

I confirm I can reproduce the HUP/reconnect bug in 0.99-2, and cannot
in 0.97-1. I also did reproduce it in 0.99-1 with the Debian-specific
patches removed. I did not bother trying with 0.99-3, since that
version depends on libio-socket-inet6-perl that breaks other parts of
my system. Anyway.


The 0.98 Changes section reads "Allow for port => 0 which lets the OS
auto assign a port on some OSes (Blackie Hlasek)". I assume this
documents the following change:

diff --git a/lib/Net/Server/Proto/TCP.pm b/lib/Net/Server/Proto/TCP.pm
index 66fdb37..68a2ef3 100644
--- a/lib/Net/Server/Proto/TCP.pm
+++ b/lib/Net/Server/Proto/TCP.pm
@@ -88,6 +88,11 @@ sub connect {
   $sock->SUPER::configure(\%args)
     or $server->fatal("Can't connect to TCP port $port on $host [$!]");
 
+  if ($port == 0 && ($port = $sock->sockport)) {
+    $sock->NS_port($port);
+    $server->log(2,"Bound to auto-assigned port $port");
+  }
+
   $server->fatal("Back sock [$!]!".caller())
     unless $sock;


The funny thing is that:

- Without this change was applied, i.e. *before* 0.98, at least one
  N::S::P::TCP user (msva-perl) did enjoy this "bind to auto-assigned
  port" feature that is supposed to be new in 0.98.
- I cannot reproduce this bug in 0.99 with this change reverted.

Let's see what happens: at HUP time, the Net::Server::bind sub tries
to reconnect previously connected sockets. It does so by trying to
make old bound socket information (from the BOUND_SOCKETS envvar)
match shiny new socket objects (in our case, a N::S::P::TCP one).
It does so by comparing $hup_string (extracted from BOUND_SOCKETS)
with $sock->hup_string. In the situation this bug report describes,
the port part of $hup_string is the port number the program was
listening on before being HUP'd, while the port part of
$sock->hup_string is "0", because it's extracted from the NS_port
attribute that was never set to anything but 0 yet (the change
I pointed out sets this to the real listening port in the connect()
method). This obviously cannot work: non-zero is never equal to zero,
so the reconnect() method is never called on the socket, and somehow
its sockport method now returns undef.


So, what to do? Reverting this change is the most appealing solution
to me, but I probably miss some actual use of it (I assume it was
initially made for good reasons, despite it breaking other parts of
the library). Also, reverting may not be an option, since the
availability of the auto-assigned port in the NS_port property was
documented in POD, and now is part of a published API:

+On systems that support it, a port value of 0 may be used to ask
+the OS to auto-assign a port.  The value of the auto-assigned port
+will be stored in the NS_port property of the Net::Server::Proto::TCP
+object and is also available in the sockport method.  When the server
+is processing a request, the $self->{server}->{sockport} property
+contains the port that was connected through.

... which is sad, since this port information, that was *already*
available using the sockport method, now is *not* available at all
after HUP.

The real fix may imply to change the way hup_string's are matched.

I am going to forward this were it belongs, that is: upstream.

Cheers,
-- 
  intrigeri <intrigeri at boum.org>
  | GnuPG key @ https://gaffer.ptitcanardnoir.org/intrigeri/intrigeri.asc
  | OTR fingerprint @ https://gaffer.ptitcanardnoir.org/intrigeri/otr.asc
  | Every now and then I get a little bit restless
  | and I dream of something wild.





More information about the pkg-perl-maintainers mailing list