Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

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

Report information
The Basics
Id: 11552
Status: resolved
Priority: 0/
Queue: IO-All

People
Owner: Nobody in particular
Requestors: shlomif [...] iglu.org.il
Cc:
AdminCc:

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



Subject: accept() closes socket after first connection if non-forked
A code like that: <<<<<<<<<<<<<<< my $server = io("localhost:$port"); while (1) { my $connection = $server->accept(); # Do something with $connection ... $connection->close(); } Show quoted text
>>>>>>>>>>>>>>>
Will fail after the first connection. The attached patch fixes this problem and adds a regression test. (it was a one line fix). Note that the patch also fixes http://rt.cpan.org/NoAuth/Bug.html?id=7448 because it prevented the package from passing all tests.
--- ./lib/IO/All/Socket.pm.orig 2005-02-18 03:16:10.433981496 +0200 +++ ./lib/IO/All/Socket.pm 2005-02-18 03:16:32.868570920 +0200 @@ -46,7 +46,7 @@ close $socket; undef $socket; } - close $server; + close $server if $self->_fork; my $io = ref($self)->new->socket_handle($socket); $io->io_handle($socket); $io->is_open(1); --- ./t/accept.t.orig 2005-02-18 02:23:37.582287808 +0200 +++ ./t/accept.t 2005-02-18 03:15:20.543565992 +0200 @@ -0,0 +1,83 @@ +use lib 't', 'lib'; +use strict; +use warnings; +use Test::More tests => 20; +use IO::All; +use IO_All_Test; +use IO::Socket::INET; + +# This test tests for the ability of a non-forking socket to handle more +# than one connection. + +my $pid = fork(); +if (! $pid) +{ + # Let the child process listen on a port + my $port = 5555; + my $accepted = 0; + while (1) + { + # Log the port to a file. + open my $out, ">t/output/server-port.t"; + print {$out} $port; + close($out); + + my $server = io("localhost:$port"); + + eval { + for my $count (1 .. 10) + { + my $connection = $server->accept(); + $accepted = 1; + $connection->print(sprintf("Ingy-%.2d", $count)); + $connection->close(); + } + }; + if ($accepted) + { + # We have a listening socket on a port, so we can continue + last; + } + } + continue + { + # Try a different port. + $port++; + } + exit(0); +} +# Let the parent process handle the testing. + +# Wait a little for the client to find a port. +sleep(1); + +open my $in, "<t/output/server-port.t"; +my $port = <$in>; +close($in); + +# TEST*2*10 +for my $c (1 .. 10) +{ + my $sock = IO::Socket::INET->new( + PeerAddr => "localhost", + PeerPort => $port, + Proto => "tcp" + ); + + ok(defined($sock), "Checking for validity of sock No. $c"); + + if (!defined($sock)) + { + last; + } + + my $data; + $sock->recv($data, 7); + + $sock->close(); + + is ($data, sprintf("Ingy-%.2d", $c), "Checking for connection No. $c."); +} + +waitpid($pid, 0); + --- ./t/synopsis2.t.orig 2005-02-18 11:20:13.834713464 +0200 +++ ./t/synopsis2.t 2005-02-18 11:20:48.301473720 +0200 @@ -8,16 +8,26 @@ # Print name and first line of all files in a directory my $dir = io('t/mydir'); ok($dir->is_dir); +my @entries; while (my $io = $dir->next) { if ($io->is_file) { - my $line = $io->name . ' - ' . $io->getline; - is($line, flip_slash scalar <DATA>); + push @entries, + +{ + 'n' => $io->name, + 'v' => ($io->name . ' - ' . $io->getline) + }; } } +for my $file (sort { $a->{'n'} cmp $b->{'n'} } @entries) +{ + my $line = $file->{'v'}; + is($line, flip_slash scalar <DATA>); +} + # Print name of all files recursively is("$_\n", flip_slash scalar <DATA>) - for grep {! /CVS|\.svn/} io('t/mydir')->all_files(0); + for sort { "$a" cmp "$b" } grep {! /CVS|\.svn/} io('t/mydir')->all_files(0); __END__ t/mydir/file1 - file1 is fun --- ./MANIFEST.orig 2005-02-18 03:19:18.132446992 +0200 +++ ./MANIFEST 2005-02-18 03:19:33.267146168 +0200 @@ -27,6 +27,7 @@ t/absolute.t t/all.t t/all2.t +t/accept.t t/assert.t t/assert2.t t/autotie.t