Skip Menu |

This queue is for tickets about the Net-Server CPAN distribution.

Report information
The Basics
Id: 72357
Status: resolved
Priority: 0/
Queue: Net-Server

People
Owner: Nobody in particular
Requestors:
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)

Attachments
08_propagate-dynamic-port-data-across-a-hup.patch



Subject: libnet-server-perl: $self->{server}->{sock} elements no longer report port numbers after a HUP
This bug has been forwarded from http://bugs.debian.org/624500 Package: libnet-server-perl Version: 0.99-1 Severity: normal With libnet-server-perl 0.97-1, i can discover the auto-assigned port number in post_bind_hook, and it work after a HUP as well (though the FD of the socket changes). With 0.99-1, i see no way to extract this information after a HUP. This causes serious problems with the msva-perl package, which currently dies after a HUP because it can't find the assigned port number. Here's example code to inspect the bound sockets for auto-assigned ports: ------------------------------------ 0 dkg@pip:~$ cat testdaemonsimple.pl #!/usr/bin/env perl use strict; use warnings; { package TestNetServer; use base qw(Net::Server::Fork); use Data::Dumper; sub post_bind_hook { my $self = shift; # if we got here, then the binding was successful. for my $sock (@{$self->{server}->{sock}}) { printf STDERR ("port: %s %s\n", $sock->show(), Dumper( [ $sock, $sock->NS_port, $sock->sockport() ] )); } } }; TestNetServer->run(port => 0); 0 dkg@pip:$ cat inspect #!/bin/sh perl ./testdaemonsimple.pl & sleep 2 lsof -p $(jobs -p %1) | grep IP kill -HUP %1 sleep 2 lsof -p $(jobs -p %1) | grep IP kill %1 wait 0 dkg@pip:~$ ------------------------------------ Here are the results at start and after a HUP, with Net::Server 0.97: ----------------------------------- 0 dkg@pip:~$ ./inspect 2011/04/28-23:12:27 TestNetServer (type Net::Server::Fork) starting! pid(10293) Binding to TCP port 0 on host * port: Ref = "Net::Server::Proto::TCP" NS_proto = "TCP" NS_port = "0" NS_host = "*" $VAR1 = [ bless( \*Symbol::GEN0, 'Net::Server::Proto::TCP' ), '0', 37534 ]; Group Not Defined. Defaulting to EGID '1000 4 20 24 25 27 29 44 46 107 109 110 115 126 1000' User Not Defined. Defaulting to EUID '1000' perl 10293 dkg 3u IPv4 846239 0t0 TCP *:37534 (LISTEN) 2011/04/28-23:12:28 Server closing! 2011/04/28-23:12:28 HUP'ing server 2011/04/28-23:12:29 TestNetServer (type Net::Server::Fork) starting! pid(10293) Binding open file descriptors Binding to TCP port 0 on host * port: Ref = "Net::Server::Proto::TCP" NS_proto = "TCP" NS_port = "0" NS_host = "*" $VAR1 = [ bless( \*Symbol::GEN0, 'Net::Server::Proto::TCP' ), '0', 37534 ]; Group Not Defined. Defaulting to EGID '1000 4 20 24 25 27 29 44 46 107 109 110 115 126 1000' User Not Defined. Defaulting to EUID '1000' perl 10293 dkg 4u IPv4 846239 0t0 TCP *:37534 (LISTEN) 2011/04/28-23:12:30 Server closing! 0 dkg@pip:~$ ----------------------------------- And here is the same thing after upgrading to 0.99-1: ----------------------------------- 0 dkg@pip:~$ ./inspect 2011/04/28-23:11:34 TestNetServer (type Net::Server::Fork) starting! pid(10173) Using default listen value of 128 Binding to TCP port 0 on host * Bound to auto-assigned port 54014 port: Ref = "Net::Server::Proto::TCP" NS_proto = "TCP" NS_port = "54014" NS_host = "*" $VAR1 = [ bless( \*Symbol::GEN0, 'Net::Server::Proto::TCP' ), 54014, 54014 ]; Group Not Defined. Defaulting to EGID '1000 4 20 24 25 27 29 44 46 107 109 110 115 126 1000' User Not Defined. Defaulting to EUID '1000' perl 10173 dkg 3u IPv4 845957 0t0 TCP *:54014 (LISTEN) 2011/04/28-23:11:36 Server closing! 2011/04/28-23:11:36 HUP'ing server 2011/04/28-23:11:36 TestNetServer (type Net::Server::Fork) starting! pid(10173) Using default listen value of 128 Binding open file descriptors port: Ref = "Net::Server::Proto::TCP" NS_proto = "TCP" NS_port = "0" NS_host = "*" $VAR1 = [ bless( \*Symbol::GEN0, 'Net::Server::Proto::TCP' ), '0', undef ]; Group Not Defined. Defaulting to EGID '1000 4 20 24 25 27 29 44 46 107 109 110 115 126 1000' User Not Defined. Defaulting to EUID '1000' perl 10173 dkg 4u IPv4 845957 0t0 TCP *:54014 (LISTEN) 2011/04/28-23:11:38 Server closing! 0 dkg@pip:~$ ----------------------------------- Note that inspection works to determine the port number on the first connection, but does *not* work after a HUP. There needs to be some way to retrieve the port number after a HUP when using an auto-assigned port. Let me know if i can help debug this further. Thanks for keeping Net::Server up-to-date in debian! --dkg -- System Information: Debian Release: wheezy/sid APT prefers testing APT policy: (500, 'testing'), (200, 'unstable'), (1, 'experimental') Architecture: i386 (i686) Kernel: Linux 2.6.38-2-686 (SMP w/1 CPU core) Locale: LANG=en_US.utf8, LC_CTYPE=en_US.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages libnet-server-perl depends on: ii libio-multiplex-perl 1.13-1 object-oriented interface to selec ii libnet-cidr-perl 0.14-1 Manipulate IPv4/IPv6 netblocks in ii perl 5.10.1-20 Larry Wall's Practical Extraction libnet-server-perl recommends no packages. Versions of packages libnet-server-perl suggests: ii libio-socket-ssl-perl 1.39-1 Perl module implementing object or -- no debconf information Thanks in advance, intrigeri, Debian Perl Group
Subject: [rt.cpan.org #72357] More info
Date: Fri, 11 Nov 2011 14:30:19 +0100
To: bug-Net-Server [...] rt.cpan.org
From: intrigeri <intrigeri+debian [...] boum.org>
Hi, I did some debugging work about this bug, see http://bugs.debian.org/624500#14 Cheers, -- intrigeri <intrigeri@boum.org> | GnuPG key @ https://gaffer.ptitcanardnoir.org/intrigeri/intrigeri.asc | OTR fingerprint @ https://gaffer.ptitcanardnoir.org/intrigeri/otr.asc | Then we'll come from the shadows.
CC: control [...] bugs.debian.org
Subject: [rt.cpan.org #72357] [PATCH] propagate Net::Server's port information across a HUP
Date: Thu, 15 Mar 2012 20:52:40 -0400
To: 624500 [...] bugs.debian.org, bug-Net-Server [...] rt.cpan.org
From: Daniel Kahn Gillmor <dkg [...] fifthhorseman.net>
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
Download (untitled)
application/pgp-signature 965b

Message body not shown because it is not plain text.

So, this actually took a bit of effort and thought to do correctly. The end result is that port => 0 or port => 'http' all do the correct thing across a HUP and NS_port reflect the correct response even after multiple hups. The logs also give better information. The code is updated as of the just released version 2.000