Skip Menu |

This queue is for tickets about the IO-Socket-IP CPAN distribution.

Report information
The Basics
Id: 98759
Status: resolved
Priority: 0/
Queue: IO-Socket-IP

People
Owner: Nobody in particular
Requestors: oleg [...] cpan.org
Cc:
AdminCc:

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



Subject: peerhost() and friends may cause croak()
If we'll call peerhost() method on IO::Socket::IP object when remote side closed connection it will croak() with message "addr is not a string". Looks like peerhostname() and others has same problem. In fact in such situation this method should return undef and set $! to ENOTCONN Test: use strict; use IO::Socket::INET; use IO::Socket::IP; use Test::More; use Errno; for my $impl ('INET', 'IP') { my ($pid, $host, $port) = make_srv(); my $s = "IO::Socket::$impl"->new("$host:$port") or die $@; $s->syswrite(rand()); sleep 1; my $peerhost = eval { $s->peerhost }; ok($! == Errno::ENOTCONN, "$impl: \$! properly set"); ok(!$@, "$impl: without exceptions") or diag $@; ok(!$peerhost, "$impl: no peerhost"); kill 15, $pid; } done_testing; sub make_srv { my $srv = IO::Socket::INET->new(Listen => 10); my $child = fork; if ($child == 0) { while (1) { my $cli = $srv->accept() or die $!; $cli->sysread(my $buf, 10); $cli->close(); } exit; } return ($child, $srv->sockhost eq "0.0.0.0" ? "127.0.0.1" : $srv->sockhost, $srv->sockport); } __END__ Output: ok 1 - INET: $! properly set ok 2 - INET: without exceptions ok 3 - INET: no peerhost ok 4 - IP: $! properly set not ok 5 - IP: without exceptions # Failed test 'IP: without exceptions' # at /tmp/srv.pl line 17. # addr is not a string at /tmp/IO-Socket-IP-0.31/lib/IO/Socket/IP.pm line 694. ok 6 - IP: no peerhost 1..6 # Looks like you failed 1 test of 6. And this may be the initiator of croak(): https://metacpan.org/source/RJBS/perl-5.20.0/cpan/Socket/Socket.xs#L542 And here is where I faced out with this problem: http://www.cpantesters.org/distro/W/WebService-Antigate.html?oncpan=1&distmat=1&version=0.05 Last LWP uses IO::Socket::IP if available. And I got 10 fail reports at one day.
Any news on this bug? Do you need a patch?
I'll take a look. Sorry; managed to miss it before. -- Paul Evans
Fixed. In next version. -- Paul Evans
Subject: rt98759.patch
=== modified file 'lib/IO/Socket/IP.pm' --- lib/IO/Socket/IP.pm 2015-01-02 19:28:19 +0000 +++ lib/IO/Socket/IP.pm 2015-01-02 19:39:50 +0000 @@ -31,7 +31,7 @@ my $AF_INET6 = eval { Socket::AF_INET6() }; # may not be defined my $AI_ADDRCONFIG = eval { Socket::AI_ADDRCONFIG() } || 0; use POSIX qw( dup2 ); -use Errno qw( EINVAL EINPROGRESS EISCONN ETIMEDOUT EWOULDBLOCK ); +use Errno qw( EINVAL EINPROGRESS EISCONN ENOTCONN ETIMEDOUT EWOULDBLOCK ); use constant HAVE_MSWIN32 => ( $^O eq "MSWin32" ); @@ -746,6 +746,9 @@ my $self = shift; my ( $addr, $flags, $xflags ) = @_; + defined $addr or + $! = ENOTCONN, return; + $flags |= NI_DGRAM if $self->socktype == SOCK_DGRAM; my ( $err, $host, $service ) = getnameinfo( $addr, $flags, $xflags || 0 ); === modified file 't/02local-server-v4.t' --- t/02local-server-v4.t 2014-09-05 15:23:52 +0000 +++ t/02local-server-v4.t 2015-01-02 19:39:50 +0000 @@ -40,6 +40,9 @@ is( $testserver->sockhost, $INADDR_LOOPBACK_HOST, "\$testserver->sockhost for $socktype" ); like( $testserver->sockport, qr/^\d+$/, "\$testserver->sockport for $socktype" ); + ok( eval { $testserver->peerport; 1 }, "\$testserver->peerport does not die for $socktype" ) + or do { chomp( my $e = $@ ); diag( "Exception was: $e" ) }; + my $socket = IO::Socket::INET->new( PeerHost => "127.0.0.1", PeerPort => $testserver->sockport, === modified file 't/05local-server-v6.t' --- t/05local-server-v6.t 2014-09-05 15:23:52 +0000 +++ t/05local-server-v6.t 2015-01-02 19:39:50 +0000 @@ -47,6 +47,9 @@ is( $testserver->sockhost, $IN6ADDR_LOOPBACK_HOST, "\$testserver->sockhost for $socktype" ); like( $testserver->sockport, qr/^\d+$/, "\$testserver->sockport for $socktype" ); + ok( eval { $testserver->peerport; 1 }, "\$testserver->peerport does not die for $socktype" ) + or do { chomp( my $e = $@ ); diag( "Exception was: $e" ) }; + my $socket = IO::Socket->new; $socket->socket( $AF_INET6, Socket->$socktype, 0 ) or die "Cannot socket() - $!";
On Fri Jan 02 14:40:49 2015, PEVANS wrote: Show quoted text
> Fixed. In next version.
Thanks. However I am not sure we need to set $! = ENOTCONN forcibly. Appropriate error will be set by underlying system call.
Released -- Paul Evans