Skip Menu |

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

Report information
The Basics
Id: 105679
Status: open
Priority: 0/
Queue: IO-Socket-IP

People
Owner: Nobody in particular
Requestors: rjray [...] blackperl.com
Cc:
AdminCc:

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



Subject: Problem binding to localhost when both IPv6 and IPv4 configured (Windows 7+Strawberry Perl)
While hunting down a test-suite bug elsewhere, I have found that Strawberry Perl on Windows 7 behaves differently than ActiveState Perl, with this module. When getting a socket connection to a "localhost" server, which has both IPv4 and IPv6 enabled (at least on Win7), the IPv6 bind fails (because the server is bound to the IPv4 address) but the second iteration of the loop in setup() fails to bind as well. I have noted that getaddrinfo() is returning two records on Strawberry, but only one record under ActiveState. The nested loops in the _io_socket_ip__configure method at lines 525-546 result in @info having two records, the IPv6 record and then the IPv4 record. Then in the setup method, the second iteration of the while-loop fails to bind to the IPv4 address. The attached sample code exhibits this behavior through the LWP::UaserAgent and HTTP::Daemon classes. HTTP::Daemon doesn't use IO::Socket::IP, and only binds to the IPv4 address for localhost. LWP::UserAgent (or a class that it uses) does use IO::Socket::IP. The script must be run in two separate terminals, one as the server and one as the client. * Run the server with "perl socket-fail.pl <port>" * Run the client with "perl socket-fail.pl <port> 1" Note that this is only exhibiting with Strawberry Perl, and I have only tried it on Windows 7. Randy -- Randy J. Ray rjray@blackperl.com randy.j.ray@gmail.com
Subject: socket-fail.pl
#!/usr/bin/env perl use strict; use warnings; use LWP::UserAgent; use HTTP::Daemon; use HTTP::Request; use HTTP::Response; use HTTP::Status; my ($port, $is_client) = @ARGV; my $host = 'localhost'; if ($is_client) { my $UA = LWP::UserAgent->new; my $req = HTTP::Request->new(HEAD => "http://$host:$port"); print ">>> Sending HEAD request\n"; my $res = $UA->request($req); print ">>> Headers from HEAD request:\n\t"; printf "%d %s\n\t", $res->code, $res->message; print $res->headers_as_string("\n\t"), "\n"; sleep 1; printf ">>> Creating POST request to %s\n", $req->uri; $req = HTTP::Request->new(POST => "http://$host:$port"); print ">>> Sending POST request\n"; $res = $UA->request($req); print ">>> Full message from POST request:\n\t"; print $res->as_string("\n\t"), "\n"; } else { my $server = HTTP::Daemon->new( ReuseAddr => 1, LocalHost => $host, LocalPort => $port, Listen => 5 ); die "Failed to create server object\n" if (! $server); $server->timeout(1); while (1) { my $conn = $server->accept; printf "<<< Accept: %s\n", ($conn || '(none)'); next if (! $conn); my $req; while ($conn and $req = $conn->get_request('headers only')) { my $res = HTTP::Response->new; $res->code(RC_OK); $res->message('OK'); $res->header(Accept => 'text/xml'); $res->content_type('text/xml'); if ($req->method eq 'HEAD') { print "<<< Sending HEAD response\n"; $conn->send_response($res); } elsif ($req->method eq 'POST') { print "<<< Sending POST response\n"; $res->content('Success'); $conn->send_response($res); } } my $eval_return = eval { local $SIG{PIPE} = sub { die "<<< server_loop: Caught SIGPIPE\n"; }; $conn->close; 1; }; if ((! $eval_return) && $@) { warn "<<< Cannot close connection: $@\n"; } undef $conn; } } exit;
On Sun Jul 05 21:27:04 2015, RJRAY wrote: Show quoted text
> While hunting down a test-suite bug elsewhere, I have found that > Strawberry Perl on Windows 7 behaves differently than ActiveState > Perl, with this module.
A tricky one. As ever, since I don't have a Windows box I find these kinds of issues very hard to track down and fix myself, but if anyone else has some input on this I'll happily provide some guidance. Show quoted text
> When getting a socket connection to a "localhost" server, which has > both IPv4 and IPv6 enabled (at least on Win7), the IPv6 bind fails > (because the server is bound to the IPv4 address) but the second > iteration of the loop in setup() fails to bind as well. I have noted > that getaddrinfo() is returning two records on Strawberry, but only > one record under ActiveState. The nested loops in the > _io_socket_ip__configure method at lines 525-546 result in @info > having two records, the IPv6 record and then the IPv4 record. Then in > the setup method, the second iteration of the while-loop fails to bind > to the IPv4 address.
That sounds odd somehow. If it's receiving the 'v6 one first and the 'v4 second, then surely the 6 couldn't fail because the 4 already has it bound? Something *else* would be getting in its way first? I'd be interested to see what it attempts to do in each iteration - have it print the three parameters to the socket() call, and the address to bind (safe-stringified, e.g. using 'unpack "H*"'). Perhaps by seeing the results of the gai call and the socket system calls it then tries to make we can make some progress. -- Paul Evans
OK, I have made a minor breakthrough on this. Pretty minor, but it might help. I remembered that Net::Server (the package I am using that in turn uses IO::Socket::IP) does logging. So I switched that on for a run, and got the following error: Bad arg length for Socket::unpack_sockaddr_in, length is 28, should be 16 at /Library/Perl/5.18/darwin-thread-multi-2level/Socket.pm line 831. Note that this isn't a Windows path... I can get this error to appear on any system for which the IPv6 localhost entry appears before the IPv4 one. I've replicated on Linux, as well. Unfortunately, the sample code I gave you above doesn't exhibit this naturally except on the Windows box. But when used in conjunction with Net::Server, I am seeing this consistently. Does this help any at all? I'll attach the log file from Net::Server, just in case... Randy -- Randy J. Ray rjray@blackperl.com randy.j.ray@gmail.com
Subject: net_server.log
Download net_server.log
application/octet-stream 796b

Message body not shown because it is not plain text.