Skip Menu |

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

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

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

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



Date: Fri, 06 Aug 2004 02:31:22 -0400
From: Tom Metro <tmetro [...] cpan.org>
To: paul [...] seamons.com, bbb [...] cpan.org, bug-Net-Server [...] rt.cpan.org
Subject: Net::Server t\Server_Fork fails on Win32
On my Win32 system (Windows NT 4.0sp6a, perl, v5.8.0, MSWin32-x86-multi-thread, ActiveState build 806) the test suite for Net::Server hangs on test 5 in Server_Fork. Looking at CPAN testers, it appears others have had problems on Win32 as well: http://testers.cpan.org/show/Net-Server.html#Net-Server-0.87 though the reported failures are different. I assume, given that earlier versions have passed tests on Win32, that the code is expected to work on Win32. With a few clarifications, I might be able to determine why the test suite is failing on Win32. Quoting from t\Server_Fork: Show quoted text
> ### find some open ports
[...] Show quoted text
> my $start_port = 20200; > my $num_ports = 1; > my @ports = (); > for my $i (0..99){ > my $sock = IO::Socket::INET->new(PeerAddr => 'localhost', > PeerPort => ($start_port + $i), > Timeout => 2, > Proto => 'tcp'); > push @ports, ($start_port + $i) if ! defined $sock; > last if $num_ports == @ports; > }
This might work better if you tested to see if the port is free by seeing if you can bind to it, rather than connect to it. Otherwise the port you find might be a port that is blocked by a firewall (which will fail later anyway) or just a slow or non-responsive server (in which case the bind will later fail). In my testing the code below seemed to also run faster. Secondly, $sock is never explicitly freed (and the port closed), though of course it goes out of scope once the 'for' block is exited. ### find some open ports my $start_port = 20200; my $port_range = 99; my $num_ports_needed = 1; my @ports = (); for my $port ($start_port .. $start_port + $port_range) { my $sock = IO::Socket::INET->new(LocalPort => $port, Listen => 1, Timeout => 2, Proto => 'tcp'); push(@ports, $port) if defined $sock; $sock = undef; last if $num_ports_needed == @ports; } Show quoted text
> if( $num_ports_needed == @ports ){ > print "ok 4\n"; > }else{ > print "not ok 4\n"; > }
Might as well do: [...] }else{ print "not ok 4\n"; print "not ok 5\n"; exit; } Show quoted text
> eval { > alarm $alarm;
alarm() doesn't work on Win32. You can use the timeout attribute for the sockets and I'd assume select() on the pipe I/O. Show quoted text
> ### parent does the client > if( $pid ){ > > <READ>; ### wait until the child writes to us > > ### connect to child > my $remote = IO::Socket::INET->new(PeerAddr => 'localhost', > PeerPort => $ports[0], > Proto => 'tcp');
[...] Show quoted text
> my $line = <$remote>; > die unless $line =~ /Net::Server/; > print $remote "exit\n"; > > ### child does the server > }else{ > close STDERR; > Net::Server::Test->run(port => $ports[0], > setsid => 1, > ); > exit; > }
So the flow here is... fork-> child parent Net::Server::Test->run() wait for text over the pipe run() calls accept() accept() writes to pipe open socket to server grabs a line does it match /Net::Server/ send "exit" Where's the code that implements the behavior on the server side that sends out "Net::Server" on connect and understands an "exit" command? I don't see a process_request() in the Net::Server::Test subclass. Is this behavior part of a default implementation? That aside, it appears that setsid => 1 is the culprit. It's side effect of closing off STDERR made it take longer to get to the bottom of things, but commenting out that attribute seems to allow the 5th test to pass, although the parent process still hangs (it outputs "Server closing!", but run() doesn't return; it appears that accept() gets called perpetually every minute or so). Here's the output from a hacked up version of t\Server_Fork: % perl -I../blib/lib Server_Fork.t 1..5 ok 1 ok 2 ok 3 Port: 20200 ok 4 PARENT: wait for pipe CHILD: run server on port: 20200 2004/08/06-02:08:43 Net::Server::Test (type Net::Server::Fork) starting! pid(-568) Binding to TCP port 20200 on host * Group Not Defined. Defaulting to EGID '0' User Not Defined. Defaulting to EUID '0' CHILD: sending "ready!" PARENT: connect to child PARENT: read from child CHILD: sending "ready!" ok 5 2004/08/06-02:08:45 Server closing! CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" CHILD: sending "ready!" Terminating on signal SIGINT(2) On a side note, the run() method doesn't seem to be formally documented, even though it is frequently referenced in the man page. Likewise for process_request(). -Tom