Open p5pRT opened 12 years ago
Perls' IO::Socket::INET core library module has a bug which prevents creating a socket that is bound to an OS-selected ephemeral port.
The standard way to bind to an available port is to set the port to zero when calling bind(). With IO::Socket::INET\, you'd do something like:
my @socket_args = ( Proto => 'udp'\, LocalPort => 0\, ); my $sock = IO::Socket::INET->new( @socket_args ) or die "socket: $@";
Except this doesn't work. Here's the offending bit from IO/Socket/INET.pm:
if($lport || ($laddr ne INADDR_ANY) || exists $arg->{Listen}) { $sock->bind($lport || 0\, $laddr) or return _error($sock\, $!\, "$!"); }
In reality\, $lport is undef instead of zero because of another bug\, but it doesn't matter either way. I verified that this if branch is not taken by using the debugger.
The same thing is true for TCP. But since the Listen option is usually supplied for TCP\, it makes the if expression evaluate to true and the bind() happens by accident.
I think the best workaround is to use the core Socket.pm module directly.
On Thu Dec 15 16:15:45 2011\, imran.patel@gmail.com wrote:
This is a bug report for perl from imran.patel@gmail.com\, generated with the help of perlbug 1.35 running under perl v5.8.8.
Perls' IO::Socket::INET core library module has a bug which prevents creating a socket that is bound to an OS-selected ephemeral port.
The standard way to bind to an available port is to set the port to zero when calling bind(). With IO::Socket::INET\, you'd do something like:
my @socket_args = ( Proto => 'udp'\, LocalPort => 0\, ); my $sock = IO::Socket::INET->new( @socket_args ) or die "socket: $@";
Except this doesn't work.
Can you be a bit more explicit as to what doesn't work?
Also\, can you try this on a currently supported version of Perl (5.12 or 5.14)?
Here's the offending bit from IO/Socket/INET.pm:
if($lport || ($laddr ne INADDR_ANY) || exists $arg->{Listen}) { $sock->bind($lport || 0\, $laddr) or return _error($sock\, $!\, "$!"); }
In reality\, $lport is undef instead of zero because of another bug\, but it doesn't matter either way. I verified that this if branch is not taken by using the debugger.
The same thing is true for TCP. But since the Listen option is usually supplied for TCP\, it makes the if expression evaluate to true and the bind() happens by accident.
I think the best workaround is to use the core Socket.pm module directly.
Thank you very much. Jim Keenan
The RT System itself - Status changed from 'new' to 'open'
On Fri\, Jan 6\, 2012 at 7:12 PM\, James E Keenan via RT \< perlbug-followup@perl.org> wrote:
On Thu Dec 15 16:15:45 2011\, imran.patel@gmail.com wrote:
This is a bug report for perl from imran.patel@gmail.com\, generated with the help of perlbug 1.35 running under perl v5.8.8.
Perls' IO::Socket::INET core library module has a bug which prevents creating a socket that is bound to an OS-selected ephemeral port.
The standard way to bind to an available port is to set the port to zero when calling bind(). With IO::Socket::INET\, you'd do something like:
my @socket_args = ( Proto => 'udp'\, LocalPort => 0\, ); my $sock = IO::Socket::INET->new( @socket_args ) or die "socket: $@";
Except this doesn't work.
Can you be a bit more explicit as to what doesn't work?
He wants bind() to be called\, and it isn't. So the real question is: Why does he want bind() to be called?
Maybe one can't query the socket to find out which port it's bound to until bind() is called or a connection is established? That would be a problem for server sockets (which would explain why bind() is explicitly called when Listen is provided).
Also\, can you try this on a currently supported version of Perl (5.12 or
5.14)?
The statement in question is still present unchanged in the latest distribution of IO (1.25).
- Eric
my @socket_args = ( Proto => 'udp'\, LocalPort => 0\, ); my $sock = IO::Socket::INET->new( @socket_args ) or die "socket: $@";
Except this doesn't work.
Can you be a bit more explicit as to what doesn't work? The UDP socket won't bind to an ephemeral port.
Also\, can you try this on a currently supported version of Perl (5.12 or 5.14)? Ok\, will do.
Imran
On Sun Jan 08 14:57:13 2012\, imran.patel@gmail.com wrote:
my @socket_args = ( � � Proto => 'udp'\, � � LocalPort => 0\, ); my $sock = IO::Socket::INET->new( @socket_args ) or die "socket: $@";
Except this doesn't work.
Can you be a bit more explicit as to what doesn't work? The UDP socket won't bind to an ephemeral port.
Also\, can you try this on a currently supported version of Perl (5.12 or 5.14)? Ok\, will do.
Have you had any opportunity to try this on a supported version of Perl?
Thank you very much. Jim Keenan
No I haven't had access to anything more modern than 5.8.8. Do you want me to provide a test case?
Imran
On Fri\, Mar 23\, 2012 at 6:29 PM\, James E Keenan via RT \< perlbug-followup@perl.org> wrote:
On Sun Jan 08 14:57:13 2012\, imran.patel@gmail.com wrote:
my @socket_args = ( � � Proto => 'udp'\, � � LocalPort => 0\, ); my $sock = IO::Socket::INET->new( @socket_args ) or die "socket: $@";
Except this doesn't work.
Can you be a bit more explicit as to what doesn't work? The UDP socket won't bind to an ephemeral port.
Also\, can you try this on a currently supported version of Perl (5.12 or 5.14)? Ok\, will do.
Have you had any opportunity to try this on a supported version of Perl?
Thank you very much. Jim Keenan
This behaviour is unchanged in the version of IO::Socket::INET bundled with v5.28.1.
However, IO::Socket::IP exhibits the behaviour that the op wanted.
use IO::Socket::IP;
my @socket_args = (
Proto => 'udp',
LocalPort => 0,
);
my $sock = IO::Socket::IP->new( @socket_args ) or die "socket: $@";
print $sock->sockport."\n";
e.g.
root@debian:~/PerlExperiments# perl socky.pl
48185
root@debian:~/PerlExperiments# perl socky.pl
33403
root@debian:~/PerlExperiments# perl socky.pl
58575
root@debian:~/PerlExperiments# perl socky.pl
35671
Is there therefore still a perceived need to keep this ticket open with the intention of changing the longstanding behaviour of IO::Socket::INET?
IO::Socket::IP
is available with core, so that does give a good way out without jumping to CPAN. But that doesn't mean we should fix this. Can the same approach that IO::Socket::IP
takes be used for this?
Migrated from rt.perl.org#106370 (status was 'open')
Searchable as RT106370$