Skip Menu |

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

Report information
The Basics
Id: 28122
Status: open
Priority: 0/
Queue: HTTP-Server-Simple

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

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



Subject: Random test results PASS 362 : FAIL 10
Now I have testes HSS 372 times and 10 times the tests failed. I repeated the test manually and it succeeded. In the logfile I see no hint about possible reasons: Running make test make[3]: Entering directory `/home/sand/.cpan/build/HTTP-Server-Simple-0.27-v1Qzsd' PERL_DL_NONLAZY=1 /home/src/perl/repoperls/installed-perls/perl/p9fpOxp/perl-5.8.0@31587/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'inc', 'blib/lib', 'blib/arch')" t/*.t t/00smoke..........ok t/01live...........# started server on 13624 early exit from `connect' stage; Connection refused at t/01live.t line 121. # Failed test 'Returns a page' # at t/01live.t line 41. # '' # doesn't match '/Congratulations/' early exit from `connect' stage; Connection refused at t/01live.t line 121. # Failed test 'knows what a request isn't' # at t/01live.t line 44. # '' # doesn't match '/bad request/i' early exit from `connect' stage; Connection refused at t/01live.t line 121. # Failed test 'HTTP/1.1 request' # at t/01live.t line 50. # '' # doesn't match '/Congratulations/' early exit from `connect' stage; Connection refused at t/01live.t line 121. # Failed test 'HTTP/0.9 request' # at t/01live.t line 53. # '' # doesn't match '/Congratulations/' # Looks like you failed 4 tests of 10. dubious ^ITest returned status 4 (wstat 1024, 0x400) DIED. FAILED tests 6-9 ^IFailed 4/10 tests, 60.00% okay t/02pod............ok t/03podcoverage....ok t/04cgi............ok Failed Test Stat Wstat Total Fail List of Failed ------------------------------------------------------------------------------- t/01live.t 4 1024 10 4 6-9 Maybe you have ideas, maybe you can improve diagnostics? Is there anything left over like a logfile of the server somewhere? Thanks,
From: sartak [...] gmail.com
On Thu Jul 12 01:10:53 2007, ANDK wrote: Show quoted text
> Now I have testes HSS 372 times and 10 times the tests failed. I > repeated the test manually and it succeeded. In the logfile I see no > hint about possible reasons:
Hi Andreas, Thanks for reporting the problem. I've tried to reproduce it and I've noticed the following: 1. On my 3GHz PC, I didn't get a single failure after 400 tests. 2. On my 500MHz laptop, I occasionally got the failure (~5%). 3. " " " " with enormous load, I almost always got the failure (damn near 100%). This leads me to believe it's a nondeterministic timing problem. Which would mean the test failures are not indicative of any actual problem with the server (it's the tests that are wrong). I'll see what I can do to fix the tests. Just adding 'sleep' calls doesn't sound like the right thing to do. :) Shawn M Moore
From: sartak [...] gmail.com
On Thu Jul 12 14:18:41 2007, SARTAK wrote: Show quoted text
> I'll see what I can do to fix the tests. Just adding 'sleep' calls > doesn't sound like the right thing to do. :)
Of course, I tried it, and it didn't fail after 10 make tests, so I've changed my mind! Here's a patch that, if the connection failed, tries to reconnect after 2s and lets the user know why the connection failed. Had to do some refactoring to avoid code duplication. Shawn M Moore
diff -Nurb HTTP-Server-Simple-0.27/t/01live.t HTTP-Server-Simple-0.27-new/t/01live.t --- HTTP-Server-Simple-0.27/t/01live.t 2007-01-17 13:31:43.000000000 -0500 +++ HTTP-Server-Simple-0.27-new/t/01live.t 2007-07-12 15:04:01.000000000 -0400 @@ -58,11 +58,12 @@ # this function may look excessive, but hopefully will be very useful # in identifying common problems -sub fetch { - my @response; - my $alarm = 0; - my $stage = "init"; +my ($alarm, $stage, $iaddr, $paddr, $proto, @response); + +sub fetch { + $alarm = 0; + $stage = "init"; my %messages = ( "init" => "inner contemplation", @@ -84,9 +85,24 @@ $alarm = 1; }; - my ($iaddr, $paddr, $proto, $message); + undef $iaddr; + undef $paddr; + undef $proto; + undef @response; + + my $message = join "", map { "$_\015\012" } @_; + + # this entire cycle should finish way before this timer expires + alarm(10); + + connection($message, 0); +} - $message = join "", map { "$_\015\012" } @_; +sub connection { + my $message = shift; + my $recursed = shift; + + my @response; my %states = ( 'init' => sub { "lookup"; }, @@ -110,9 +126,6 @@ "close" => sub { close SOCK; "done"; }, ); - # this entire cycle should finish way before this timer expires - alarm(5); - my $next; $stage = $next while (!$alarm && $stage ne "done" @@ -120,9 +133,14 @@ warn "early exit from `$stage' stage; $!" unless $next; + if ($stage eq 'connect' && !$recursed) { + warn "this is probably due to a timing problem -- if you have a slower CPU or it's under high load, the server may not have had enough time to initialize everything before the test tried to connect to it. trying again in 2s"; + # reset alarm because sleep uses SIGALRM + alarm 0; sleep 2; alarm 8; + return connection($message, 1); + } + # bank on the test testing for something in the response. return join "", @response; - - } diff -Nurb HTTP-Server-Simple-0.27/t/04cgi.t HTTP-Server-Simple-0.27-new/t/04cgi.t --- HTTP-Server-Simple-0.27/t/04cgi.t 2007-01-17 13:31:43.000000000 -0500 +++ HTTP-Server-Simple-0.27-new/t/04cgi.t 2007-07-12 15:04:29.000000000 -0400 @@ -69,12 +69,14 @@ wait or die "counldn't wait for sub-process completion"; } +# this function may look excessive, but hopefully will be very useful +# in identifying common problems -sub fetch { +my ($alarm, $stage, $iaddr, $paddr, $proto, @response); - my @response; - my $alarm = 0; - my $stage = "init"; +sub fetch { + $alarm = 0; + $stage = "init"; my %messages = ( "init" => "inner contemplation", @@ -96,9 +98,24 @@ $alarm = 1; }; - my ($iaddr, $paddr, $proto, $message); + undef $iaddr; + undef $paddr; + undef $proto; + undef @response; - $message = join "", map { "$_\015\012" } @_; + my $message = join "", map { "$_\015\012" } @_; + + # this entire cycle should finish way before this timer expires + alarm(10); + + connection($message, 0); +} + +sub connection { + my $message = shift; + my $recursed = shift; + + my @response; my %states = ( 'init' => sub { "lookup"; }, @@ -122,9 +139,6 @@ "close" => sub { close SOCK; "done"; }, ); - # this entire cycle should finish way before this timer expires - alarm(5); - my $next; $stage = $next while (!$alarm && $stage ne "done" @@ -132,12 +146,18 @@ warn "early exit from `$stage' stage; $!" unless $next; + if ($stage eq 'connect' && !$recursed) { + warn "this is probably due to a timing problem -- if you have a slower CPU or it's under high load, the server may not have had enough time to initialize everything before the test tried to connect to it. trying again in 2s"; + # reset alarm because sleep uses SIGALRM + alarm 0; sleep 2; alarm 8; + return connection($message, 1); + } + # bank on the test testing for something in the response. return join "", @response; - - } + { package CGIServer; use base qw(HTTP::Server::Simple::CGI);
From: sartak [...] gmail.com
On Thu Jul 12 14:18:41 2007, SARTAK wrote: Show quoted text
> I'll see what I can do to fix the tests. Just adding 'sleep' calls > doesn't sound like the right thing to do. :)
Of course, I tried it, and it didn't fail after 10 make tests, so I've changed my mind! Here's a patch that, if the connection failed, tries to reconnect after 2s and lets the user know why the connection failed. Had to do some refactoring to avoid code duplication. Shawn M Moore
diff -Nurb HTTP-Server-Simple-0.27/t/01live.t HTTP-Server-Simple-0.27-new/t/01live.t --- HTTP-Server-Simple-0.27/t/01live.t 2007-01-17 13:31:43.000000000 -0500 +++ HTTP-Server-Simple-0.27-new/t/01live.t 2007-07-12 15:04:01.000000000 -0400 @@ -58,11 +58,12 @@ # this function may look excessive, but hopefully will be very useful # in identifying common problems -sub fetch { - my @response; - my $alarm = 0; - my $stage = "init"; +my ($alarm, $stage, $iaddr, $paddr, $proto, @response); + +sub fetch { + $alarm = 0; + $stage = "init"; my %messages = ( "init" => "inner contemplation", @@ -84,9 +85,24 @@ $alarm = 1; }; - my ($iaddr, $paddr, $proto, $message); + undef $iaddr; + undef $paddr; + undef $proto; + undef @response; + + my $message = join "", map { "$_\015\012" } @_; + + # this entire cycle should finish way before this timer expires + alarm(10); + + connection($message, 0); +} - $message = join "", map { "$_\015\012" } @_; +sub connection { + my $message = shift; + my $recursed = shift; + + my @response; my %states = ( 'init' => sub { "lookup"; }, @@ -110,9 +126,6 @@ "close" => sub { close SOCK; "done"; }, ); - # this entire cycle should finish way before this timer expires - alarm(5); - my $next; $stage = $next while (!$alarm && $stage ne "done" @@ -120,9 +133,14 @@ warn "early exit from `$stage' stage; $!" unless $next; + if ($stage eq 'connect' && !$recursed) { + warn "this is probably due to a timing problem -- if you have a slower CPU or it's under high load, the server may not have had enough time to initialize everything before the test tried to connect to it. trying again in 2s"; + # reset alarm because sleep uses SIGALRM + alarm 0; sleep 2; alarm 8; + return connection($message, 1); + } + # bank on the test testing for something in the response. return join "", @response; - - } diff -Nurb HTTP-Server-Simple-0.27/t/04cgi.t HTTP-Server-Simple-0.27-new/t/04cgi.t --- HTTP-Server-Simple-0.27/t/04cgi.t 2007-01-17 13:31:43.000000000 -0500 +++ HTTP-Server-Simple-0.27-new/t/04cgi.t 2007-07-12 15:04:29.000000000 -0400 @@ -69,12 +69,14 @@ wait or die "counldn't wait for sub-process completion"; } +# this function may look excessive, but hopefully will be very useful +# in identifying common problems -sub fetch { +my ($alarm, $stage, $iaddr, $paddr, $proto, @response); - my @response; - my $alarm = 0; - my $stage = "init"; +sub fetch { + $alarm = 0; + $stage = "init"; my %messages = ( "init" => "inner contemplation", @@ -96,9 +98,24 @@ $alarm = 1; }; - my ($iaddr, $paddr, $proto, $message); + undef $iaddr; + undef $paddr; + undef $proto; + undef @response; - $message = join "", map { "$_\015\012" } @_; + my $message = join "", map { "$_\015\012" } @_; + + # this entire cycle should finish way before this timer expires + alarm(10); + + connection($message, 0); +} + +sub connection { + my $message = shift; + my $recursed = shift; + + my @response; my %states = ( 'init' => sub { "lookup"; }, @@ -122,9 +139,6 @@ "close" => sub { close SOCK; "done"; }, ); - # this entire cycle should finish way before this timer expires - alarm(5); - my $next; $stage = $next while (!$alarm && $stage ne "done" @@ -132,12 +146,18 @@ warn "early exit from `$stage' stage; $!" unless $next; + if ($stage eq 'connect' && !$recursed) { + warn "this is probably due to a timing problem -- if you have a slower CPU or it's under high load, the server may not have had enough time to initialize everything before the test tried to connect to it. trying again in 2s"; + # reset alarm because sleep uses SIGALRM + alarm 0; sleep 2; alarm 8; + return connection($message, 1); + } + # bank on the test testing for something in the response. return join "", @response; - - } + { package CGIServer; use base qw(HTTP::Server::Simple::CGI);
From: ntyni [...] iki.fi
On Thu Jul 12 14:18:41 2007, SARTAK wrote: Show quoted text
> 1. On my 3GHz PC, I didn't get a single failure after 400 tests. > 2. On my 500MHz laptop, I occasionally got the failure (~5%). > 3. " " " " with enormous load, I almost always got the > failure (damn near 100%). > > This leads me to believe it's a nondeterministic timing problem. Which > would mean the test failures are not indicative of any actual problem > with the server (it's the tests that are wrong).
Hi, I think the fundamental problem here is that the background() method returns before the server is ready to answer requests. This means that everybody using it has to wait a non-deterministic time first. This has hit Test::WWW::Mechanize - see CPAN ticket #27168 and Debian bug #439470: http://rt.cpan.org/Public/Bug/Display.html?id=27168 http://bugs.debian.org/439470 It would be nice if background() could wait until the server is ready. I suppose this would not be very hard to implement: just use a pipe between the processes when forking, and make the child send a message when it's ready. I can take a shot at a patch if you like. For the record, we're tracking this issue as a separate Debian bug: http://bugs.debian.org/439724 Thanks for your work, -- Niko Tyni (Debian Perl Group) ntyni@iki.fi
From: ntyni [...] iki.fi
On Mon Aug 27 06:46:48 2007, ntyni@iki.fi wrote: Show quoted text
> It would be nice if background() could wait until the server is ready. I > suppose this would not be very hard to implement: just use a pipe > between the processes when forking, and make the child send a message > when it's ready. I can take a shot at a patch if you like.
I'm attaching three patches: a testcase that fails with the current version, and two alternative proposals for fixing this. The first one makes the child send a SIGUSR1 to the parent when it's ready, the second one says "OK" into a pipe between them. Please consider adding something like this to make the behaviour deterministic. Cheers, -- Niko Tyni ntyni@iki.fi
From b728289854c85fc0fe09547b3dc8691f2b167898 Mon Sep 17 00:00:00 2001 From: Niko Tyni <ntyni@iki.fi> Date: Sun, 16 Sep 2007 13:40:24 +0300 Subject: [PATCH] Pipe version: parent waits for the child to say "OK" via a pipe. --- lib/HTTP/Server/Simple.pm | 29 ++++++++++++++++++++++++++++- 1 files changed, 28 insertions(+), 1 deletions(-) diff --git a/lib/HTTP/Server/Simple.pm b/lib/HTTP/Server/Simple.pm index 98049d2..107322f 100755 --- a/lib/HTTP/Server/Simple.pm +++ b/lib/HTTP/Server/Simple.pm @@ -5,6 +5,7 @@ use FileHandle; use Socket; use Carp; use URI::Escape; +use IO::Select; use vars qw($VERSION $bad_request_doc); $VERSION = '0.27'; @@ -161,15 +162,31 @@ Run the server in the background. returns pid. sub background { my $self = shift; + + # set up a pipe so the child can tell the parent when it's ready + # to accept requests + my ($readfh, $writefh) = FileHandle::pipe; + my $child = fork; die "Can't fork: $!" unless defined($child); - return $child if $child; + if ($child) { # parent + my $s = IO::Select->new; + $s->add($readfh); + my @ready = $s->can_read(5); + die("child unresponsive for 5 seconds") if !@ready; + my $response = <$readfh>; + chomp $response; + die("child is confused: answer '$response' != 'OK'") + if $response ne "OK"; + return $child; + } if ( $^O !~ /MSWin32/ ) { require POSIX; POSIX::setsid() or die "Can't start a new session: $!"; } + $self->{_parent_handle} = $writefh; $self->run(); } @@ -229,6 +246,7 @@ sub run { $self->after_setup_listener(); *{"$pkg\::run"} = $self->_default_run; } + $self->_maybe_tell_parent(); $pkg->run( port => $self->port ); } @@ -335,6 +353,15 @@ sub _process_request { } } +sub _maybe_tell_parent { + # inform the parent process that we're ready, if applicable + my $self = shift; + my $handle = $self->{_parent_handle}; + return if !$handle; + print $handle "OK\n"; + close $handle; + delete $self->{_parent_handle}; +} -- 1.5.3.1
From f7a9df060539718c9bbd46da436539e247b27bc7 Mon Sep 17 00:00:00 2001 From: Niko Tyni <ntyni@iki.fi> Date: Sun, 16 Sep 2007 13:35:17 +0300 Subject: [PATCH] add testcase for CPAN #28122 --- t/01live.t | 22 ++++++++++++++++++---- 1 files changed, 18 insertions(+), 4 deletions(-) diff --git a/t/01live.t b/t/01live.t index 0e91384..5e8effc 100644 --- a/t/01live.t +++ b/t/01live.t @@ -1,7 +1,7 @@ # -*- perl -*- use Socket; -use Test::More tests => 10; +use Test::More tests => 14; use strict; # This script assumes that `localhost' will resolve to a local IP @@ -11,16 +11,31 @@ use constant PORT => 13432; use HTTP::Server::Simple; +package SlowServer; +# This test class just waits a while before it starts +# accepting connections. This makes sure that CPAN #28122 is fixed: +# background() shouldn't return prematurely. + +use base qw(HTTP::Server::Simple::CGI); +sub setup_listener { + my $self = shift; + sleep 2; + $self->SUPER::setup_listener(); +} +1; +package main; + my $DEBUG = 1 if @ARGV; +my @classes = (qw(HTTP::Server::Simple SlowServer)); +for my $class (@classes) { - my $s=HTTP::Server::Simple->new(PORT); + my $s = $class->new(PORT); is($s->port(),PORT,"Constructor set port correctly"); my $pid=$s->background(); like($pid, '/^-?\d+$/', 'pid is numeric'); - select(undef,undef,undef,0.2); # wait a sec my $content=fetch("GET / HTTP/1.1", ""); @@ -34,7 +49,6 @@ my $DEBUG = 1 if @ARGV; $s->host("localhost"); my $pid=$s->background(); diag("started server on $pid"); - select(undef,undef,undef,0.2); # wait a sec like($pid, '/^-?\d+$/', 'pid is numeric'); my $content=fetch("GET / HTTP/1.1", ""); -- 1.5.3.1
From c810bff8000a871b40fa58aaef52bd25d09c7a38 Mon Sep 17 00:00:00 2001 From: Niko Tyni <ntyni@iki.fi> Date: Sun, 16 Sep 2007 13:37:55 +0300 Subject: [PATCH] Signal version: child sends SIGUSR1 to the parent when it's ready. --- lib/HTTP/Server/Simple.pm | 51 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lib/HTTP/Server/Simple.pm b/lib/HTTP/Server/Simple.pm index 98049d2..f5a5011 100755 --- a/lib/HTTP/Server/Simple.pm +++ b/lib/HTTP/Server/Simple.pm @@ -161,9 +161,30 @@ Run the server in the background. returns pid. sub background { my $self = shift; - my $child = fork; - die "Can't fork: $!" unless defined($child); - return $child if $child; + my $parent_pid = $$; + + # fork, then wait for the child to send us an + # USR1 signal from _signal_parent() + + { # scope for the local sighandler below + my $gotsig = 0; + local $SIG{USR1} = sub { $gotsig = 1; }; + my $child = fork; + die "Can't fork: $!" unless defined($child); + if ($child) { # parent + my $sleeptime = 5; + my $i = 0; + while (!$gotsig && $sleeptime > 0) { + $sleeptime -= sleep $sleeptime; + die("infinite loop while waiting for the child?") + if $i++ > 10; + } + die("Child unresponsive for 5 seconds, giving up") + if !$gotsig; + return $child; + } + } + $self->{_parent_pid} = $parent_pid; if ( $^O !~ /MSWin32/ ) { require POSIX; @@ -229,6 +250,7 @@ sub run { $self->after_setup_listener(); *{"$pkg\::run"} = $self->_default_run; } + $self->_signal_parent; $pkg->run( port => $self->port ); } @@ -335,7 +357,30 @@ sub _process_request { } } +sub _signal_parent { + my $self = shift; + + # tell the parent that we are ready to accept requests, + # if applicable + my $parent = $self->{_parent_pid}; + if ($parent) { + require Config; + defined $Config::Config{sig_name} || die "No sigs?"; + my %signo; + my $i = 0; + foreach my $name (split(' ', $Config::Config{sig_name})) { + $signo{$name} = $i; + $i++; + } + + die("No USR1 signal available?") if !$signo{USR1}; + my $ret = kill $signo{USR1}, $parent; + die("Failed to signal parent process $parent") if !$ret; + delete $self->{_parent_pid}; + } + return; +} -- 1.5.3.1
From: ntyni [...] iki.fi
On Sun Sep 16 06:46:51 2007, ntyni@iki.fi wrote: Show quoted text
> On Mon Aug 27 06:46:48 2007, ntyni@iki.fi wrote: >
> > It would be nice if background() could wait until the server is ready. I > > suppose this would not be very hard to implement: just use a pipe > > between the processes when forking, and make the child send a message > > when it's ready. I can take a shot at a patch if you like.
> > I'm attaching three patches: a testcase that fails with the current > version, and two alternative proposals for fixing this. The first one > makes the child send a SIGUSR1 to the parent when it's ready, the second > one says "OK" into a pipe between them. > > Please consider adding something like this to make the behaviour > deterministic.
We have had the signal version of the patch in Debian for some time now, and it was recently noticed that it breaks the test suite of Test-HTTP-Server-Simple, which uses SIGUSR1 too. See <http://bugs.debian.org/477227> for more information. In hindsight, using a user signal in a library was probably a bad idea. So the pipe version would seem to be the better choice. I see there have been several releases since, and my test case patch doesn't apply cleanly anymore. I'm attaching an updated version of the patches. Please let me know if there's something else I can do to help get this integrated. I really think this is a bug worth fixing. Many thanks for your work on free software, -- Niko Tyni ntyni@debian.org
diff --git a/lib/HTTP/Server/Simple.pm b/lib/HTTP/Server/Simple.pm index ba2430e..f5bcfea 100755 --- a/lib/HTTP/Server/Simple.pm +++ b/lib/HTTP/Server/Simple.pm @@ -6,6 +6,7 @@ use FileHandle; use Socket; use Carp; use URI::Escape; +use IO::Select; use vars qw($VERSION $bad_request_doc); $VERSION = '0.31'; @@ -215,15 +216,31 @@ Run the server in the background. returns pid. sub background { my $self = shift; + + # set up a pipe so the child can tell the parent when it's ready + # to accept requests + my ($readfh, $writefh) = FileHandle::pipe; + my $child = fork; die "Can't fork: $!" unless defined($child); - return $child if $child; + if ($child) { # parent + my $s = IO::Select->new; + $s->add($readfh); + my @ready = $s->can_read(5); + die("child unresponsive for 5 seconds") if !@ready; + my $response = <$readfh>; + chomp $response; + die("child is confused: answer '$response' != 'OK'") + if $response ne "OK"; + return $child; + } if ( $^O !~ /MSWin32/ ) { require POSIX; POSIX::setsid() or die "Can't start a new session: $!"; } + $self->{_parent_handle} = $writefh; $self->run(); } @@ -263,6 +280,7 @@ sub run { $self->after_setup_listener(); *{"$pkg\::run"} = $self->_default_run; } + $self->_maybe_tell_parent(); local $SIG{HUP} = sub { $SERVER_SHOULD_RUN = 0; }; @@ -400,6 +418,15 @@ sub _process_request { } } +sub _maybe_tell_parent { + # inform the parent process that we're ready, if applicable + my $self = shift; + my $handle = $self->{_parent_handle}; + return if !$handle; + print $handle "OK\n"; + close $handle; + delete $self->{_parent_handle}; +} diff --git a/t/01live.t b/t/01live.t index e1b35a2..e779731 100644 --- a/t/01live.t +++ b/t/01live.t @@ -1,7 +1,7 @@ # -*- perl -*- use Socket; -use Test::More tests => 10; +use Test::More tests => 14; use strict; # This script assumes that `localhost' will resolve to a local IP @@ -12,16 +12,31 @@ my $PORT = 8000 + $$; use HTTP::Server::Simple; +package SlowServer; +# This test class just waits a while before it starts +# accepting connections. This makes sure that CPAN #28122 is fixed: +# background() shouldn't return prematurely. + +use base qw(HTTP::Server::Simple::CGI); +sub setup_listener { + my $self = shift; + sleep 2; + $self->SUPER::setup_listener(); +} +1; +package main; + my $DEBUG = 1 if @ARGV; +my @classes = (qw(HTTP::Server::Simple SlowServer)); +for my $class (@classes) { - my $s=HTTP::Server::Simple->new($PORT); + my $s = $class->new($PORT); is($s->port(),$PORT,"Constructor set port correctly"); my $pid=$s->background(); like($pid, '/^-?\d+$/', 'pid is numeric'); - select(undef,undef,undef,0.2); # wait a sec my $content=fetch("GET / HTTP/1.1", ""); @@ -35,7 +50,6 @@ my $DEBUG = 1 if @ARGV; $s->host("localhost"); my $pid=$s->background(); diag("started server on $pid"); - select(undef,undef,undef,0.2); # wait a sec like($pid, '/^-?\d+$/', 'pid is numeric'); my $content=fetch("GET / HTTP/1.1", "");
CC: Hans Dieter Pearcey <hdp [...] weftsoar.net>
Subject: [PATCH] use tempfile as semaphore to background() [CPAN #28122]
Date: Sun, 22 Feb 2009 18:32:44 -0500
To: bug-HTTP-Server-Simple [...] rt.cpan.org
From: Hans Dieter Pearcey <hdp [...] weftsoar.net>
--- lib/HTTP/Server/Simple.pm | 14 ++++++++++++-- 1 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/HTTP/Server/Simple.pm b/lib/HTTP/Server/Simple.pm index fa6b2c6..a004437 100755 --- a/lib/HTTP/Server/Simple.pm +++ b/lib/HTTP/Server/Simple.pm @@ -206,15 +206,25 @@ started process. Any arguments will be passed through to L</run>. sub background { my $self = shift; + require File::Temp; + my ($fh, $filename) = File::Temp::tempfile(); + unlink($filename); my $child = fork; croak "Can't fork: $!" unless defined($child); - return $child if $child; + if ($child) { + while (eof($fh)) { + select(undef, undef, undef, 0.1); + seek($fh, 0, 0); + } + return $child; + } if ( $^O !~ /MSWin32/ ) { require POSIX; POSIX::setsid() or croak "Can't start a new session: $!"; } + $self->{after_setup} = sub { print {$fh} 1; close $fh }; $self->run(@_); } @@ -660,7 +670,7 @@ sub setup_listener { ) or croak "bind to @{[$self->host||'*']}:@{[$self->port]}: $!"; listen( HTTPDaemon, SOMAXCONN ) or croak "listen: $!"; - + $self->{after_setup} && $self->{after_setup}->(); } -- 1.6.1.2