Skip Menu |

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

Report information
The Basics
Id: 19564
Status: resolved
Priority: 0/
Queue: Test-HTTP-Server-Simple

People
Owner: Nobody in particular
Requestors: agentzh [...] gmail.com
Cc:
AdminCc:

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



Subject: Version 0.02 fails on ActivePerl 5.8.8 of Win32
Test::HTTP::Server::Simple 0.02 fails on ActivePerl 5.8.8 while the older version (0.01) can pass all the tests there. The error messages I got while I was trying to install the version 0.02 via the cpan utility are as follows: D:\Perl\bin\perl.exe "-MExtUtils::Command::MM" "-e" "test_harness(0, 'bl ib\lib', 'blib\arch')" t/*.t t/00.load.........ok 1/1# Testing Test::HTTP::Server::Simple 0.02 t/00.load.........ok t/01.basic........No such signal: SIGUSR1 at D:\Perl\cpan\build\Test-HTTP-Server -Simple-0.02\blib\lib/Test/HTTP/Server/Simple.pm line 96, <DATA> line 16. No such signal: SIGUSR1 at D:\Perl\cpan\build\Test-HTTP-Server-Simple-0.02\blib\ lib/Test/HTTP/Server/Simple.pm line 96, <DATA> line 16. No such signal: SIGUSR1 at t/01.basic.t line 9, <DATA> line 16. No such signal: SIGUSR1 at D:\Perl\cpan\build\Test-HTTP-Server-Simple-0.02\blib\ lib/Test/HTTP/Server/Simple.pm line 96, <DATA> line 16. t/01.basic........ok 1/6No such signal: SIGUSR1 at D:\Perl\cpan\build\Test-HTTP- Server-Simple-0.02\blib\lib/Test/HTTP/Server/Simple.pm line 96, <DATA> line 16. No such signal: SIGUSR1 at t/01.basic.t line 15, <DATA> line 16. No such signal: SIGUSR1 at D:\Perl\cpan\build\Test-HTTP-Server-Simple-0.02\blib\ lib/Test/HTTP/Server/Simple.pm line 96, <DATA> line 16. No such signal: SIGUSR1 at D:\Perl\cpan\build\Test-HTTP-Server-Simple-0.02\blib\ lib/Test/HTTP/Server/Simple.pm line 96, <DATA> line 16. No such signal: SIGUSR1 at t/01.basic.t line 19, <DATA> line 16. # Failed test 'start up correctly' # in t/01.basic.t at line 21. # STDOUT is: # not ok 1 - beep # # not: # ok 1 - beep # # as expected # STDERR is: # # Failed test 'beep' t/01.basic........NOK 3# # in t/01.basic.t at line 19. # # HTTP::Server::Simple->background failed: Unrecognized signal name "USR1" at D:\Perl\cpan\build\Test-HTTP-Server-Simple-0.02\blib\lib/Test/HTTP/Server/Simple .pm line 140, <DATA> line 16. # # not: # # Waiting for child to start up... # # as expected t/01.basic........NOK 4# Failed test in t/01.basic.t at line 23. # got: undef # expected: 'http://localhost:9583' t/01.basic........NOK 5# Failed test 'start up correctly (with default message )' # in t/01.basic.t at line 28. # STDOUT is: # not ok 1 - started server # # not: # ok 1 - started server # # as expected # STDERR is: # # Failed test 'started server' # # in t/01.basic.t at line 26. # # HTTP::Server::Simple->background failed: Unrecognized signal name "USR1" at D:\Perl\cpan\build\Test-HTTP-Server-Simple-0.02\blib\lib/Test/HTTP/Server/Simple .pm line 140, <DATA> line 16. # # not: # # Waiting for child to start up... # # as expected t/01.basic........NOK 6# Failed test in t/01.basic.t at line 30. # got: undef # expected: 'http://localhost:9384' (segfault here) Hopefully the author will fix this Win32 issue because Jifty currently depends on this module. :) Cheers, Agent
On Mon May 29 04:01:28 2006, AGENT wrote: Show quoted text
> Test::HTTP::Server::Simple 0.02 fails on ActivePerl 5.8.8 while the > older version (0.01) can pass all the tests there.
That is correct. THHS uses signals which windows doesn't support. I would like THHS to support Windows, but I'm not an expert on their IPC capabilities. I'd be happy to accept any patches to fix this. --dave -- David Glasser
Hi dave, I have some good and some bad news for you: The good is that it's possible to make the child (which is really a thread in the main process) signal the parent that it's ready without resorting to (POSIX) signals. Here is some code that exhibits this: use Win32::Event; my $event = Win32::Event->new(); my $pid; if ($pid = fork) { # child print "$pid: Sleep some\n"; sleep 3; print "$pid: Done sleeping\n"; $event->pulse(); print "$pid: Exiting.\n"; exit; } else { # parent print "$pid: Waiting on event\n"; $event->wait(); print "$pid: Done waiting\n"; exit; } The bad news is two-fold. First, if the child doesn't exit, the parent won't either. If you replace the child's exit() with a "sleep 1 while 1;", then the parent will exit, but the program continues to run forever. Second, there is, to my knowledge, no way to *safely* kill a child "process". Since this whole fork() thing is implemented internally with threads, using kill() to send the child a KILL signal might make perl dump core. Sometimes... I don't know of workarounds for these two problems. They may exist, but I'm just another Linux user with some Win32 exposure. Steffen
CC: undisclosed-recipients: ;
Subject: Re: [rt.cpan.org #19564] Version 0.02 fails on ActivePerl 5.8.8 of Win32
Date: Fri, 15 Dec 2006 11:55:41 -0500
To: bug-test-http-server-simple [...] rt.cpan.org
From: jesse <jesse [...] fsck.com>
Thanks! this sounds like...at least much more of a start than we had before. On Thu, Dec 14, 2006 at 03:05:08PM -0500, Steffen M?ller via RT wrote: Show quoted text
> > Queue: Test-HTTP-Server-Simple > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=19564 > > > Hi dave, > > I have some good and some bad news for you: > > The good is that it's possible to make the child (which is really a > thread in the main process) signal the parent that it's ready without > resorting to (POSIX) signals. Here is some code that exhibits this: > > > use Win32::Event; > my $event = Win32::Event->new(); > > my $pid; > if ($pid = fork) { > # child > print "$pid: Sleep some\n"; > sleep 3; > print "$pid: Done sleeping\n"; > $event->pulse(); > print "$pid: Exiting.\n"; > exit; > } > else { > # parent > print "$pid: Waiting on event\n"; > $event->wait(); > print "$pid: Done waiting\n"; > exit; > } > > The bad news is two-fold. First, if the child doesn't exit, the parent > won't either. If you replace the child's exit() with a "sleep 1 while > 1;", then the parent will exit, but the program continues to run forever. > Second, there is, to my knowledge, no way to *safely* kill a child > "process". Since this whole fork() thing is implemented internally with > threads, using kill() to send the child a KILL signal might make perl > dump core. Sometimes... > > I don't know of workarounds for these two problems. They may exist, but > I'm just another Linux user with some Win32 exposure. > > Steffen >
--
On Fri Dec 15 11:55:49 2006, jesse@fsck.com wrote: Show quoted text
> Thanks! this sounds like...at least much more of a start than we had > before.
I got it to work! It's not great and uses hack after hack, but the attached Test/HTTP/Server/Simple.pm passes its tests on win32. I didn't document anything nor modified the comments according to what I did. That's left for the maintainer ;) Also, I haven't tested whether my changes break other OS's. There are at least three gotchas with this: - On very, very slow computers, it might happen that one gets an "all subtests passed and the process returned status "9" thereafter. ==> The main process exited too quickly for the child thread to be reaped completely -- or so. - Using kill 9 on win32 to kill the children ==> no Devel::Cover support. - Also following from kill 9: if the test process is running lots of server instances, this is a problem because the memory that was used by the thread will not be reclaimed. Solution: Use separate test scripts if you plan to run lots of server instances and fear they might end up eating all memory. I doubt it's possible to make this work much better on win32 without a lot of effort. Steffen
package Test::HTTP::Server::Simple; our $VERSION = '0.03'; use warnings; use strict; use Carp; use NEXT; use Test::Builder; my $Tester = Test::Builder->new; use constant WIN32 => $^O =~ /win32/i; my $Event; # used on win32 only if (WIN32) { require Win32::Event; $Event = Win32::Event->new(); } =head1 NAME Test::HTTP::Server::Simple - Test::More functions for HTTP::Server::Simple =head1 SYNOPSIS package My::WebServer; use base qw/Test::HTTP::Server::Simple HTTP::Server::Simple/; package main; use Test::More tests => 42; my $s = My::WebServer->new; my $url_root = $s->started_ok("start up my web server); # connect to "$url_root/cool/site" and test with Test::WWW::Mechanize, # Test::HTML::Tidy, etc =head1 DESCRIPTION This mixin class provides methods to test an L<HTTP::Server::Simple>-based web server. Currently, it provides only one such method: C<started_ok>. =over 4 =item started_ok [$text] C<started_ok> takes an optional test description. The server needs to have been configured (specifically, its port needs to have been set), but it should not have been run or backgrounded. C<started_ok> calls C<background> on the server, which forks it to run in the background. L<Test::HTTP::Server::Simple> takes care of killing the server when your test script dies, even if you kill your test script with an interrupt. C<started_ok> returns the URL C<http://localhost:$port> which you can use to connect to your server. Note that if the child process dies, or never gets around to listening for connections, this just hangs. (This may be fixed in a future version.) Also, it probably won't work if you use a custom L<Net::Server> in your server. =cut my @CHILD_PIDS; # If an interrupt kills perl, END blocks are not run. This # essentially converts interrupts (like CTRL-C) into a standard # perl exit (even if we're inside an eval {}). $SIG{INT} = sub { warn "INT:$$"; exit }; END { if (WIN32) { # INT won't do since the server is doing a blocking read # which isn't interrupted by anything but KILL on win32. kill 9, $_ for @CHILD_PIDS; sleep 1; foreach (@CHILD_PIDS) { sleep 1 while kill 0, $_; } } else { kill 'USR1', @CHILD_PIDS if @CHILD_PIDS; } } sub started_ok { my $self = shift; my $text = shift; $text = 'started server' unless defined $text; my $port = $self->port; my $pid; $self->{'test_http_server_simple_parent_pid'} = $$; my $child_loaded_yet = 0; # So this is a little complicated. The following signal handler does two # ENTIRELY DIFFERENT things: # # In the parent, it just sets $child_loaded_yet, which breaks out of the # while loop below. It's activated by the kid sending it a SIGUSR1 after # it runs setup_listener # # In the kid, it sets the variable, but that's basically pointless since # the call to ->background doesn't actually return in the kid. But also, # it exits. And when you actually exit with 'exit' (as opposed to being # killed by a signal) END blocks get run. Which means that you can use # Devel::Cover to test the kid's coverage. This one is activated by the # parent's END block in this file. local %SIG; if (not WIN32) { $SIG{'USR1'} = sub { $child_loaded_yet = 1; exit unless $self->{'test_http_server_simple_parent_pid'} == $$ } } # XXX TODO FIXME should somehow not have the signal handler around in the # kid # Comment: How about if ($pid) { $SIG{'USR1'} = ... }? eval { $pid = $self->background; }; if ($@) { my $error_text = $@; # In case the next line changes it. $Tester->ok(0, $text); $Tester->diag("HTTP::Server::Simple->background failed: $error_text"); return; } unless ($pid =~ /^-?\d+$/) { $Tester->ok(0, $text); $Tester->diag("HTTP::Server::Simple->background didn't return a valid PID"); return; } push @CHILD_PIDS, $pid; if (WIN32) { $Event->wait(); } else { 1 while not $child_loaded_yet; } $Tester->ok(1, $text); return "http://localhost:$port"; } =begin private =head2 setup_listener We send a signal to the parent here. We need to use NEXT because this is a mixin. =end private =cut sub setup_listener { my $self = shift; $self->NEXT::setup_listener; if (WIN32) { $Event->pulse(); } else { kill 'USR1', $self->{'test_http_server_simple_parent_pid'}; } } =back =head1 DEPENDENCIES L<Test::Builder>, L<HTTP::Server::Simple>, L<NEXT>. =head1 INCOMPATIBILITIES None reported. =head1 BUGS AND LIMITATIONS Installs an interrupt signal handler, which may override any that another part of your program has installed. Please report any bugs or feature requests to C<bug-test-http-server-simple@rt.cpan.org>, or through the web interface at L<http://rt.cpan.org>. =head1 AUTHOR David Glasser C<< <glasser@bestpractical.com> >> =head1 LICENCE AND COPYRIGHT Copyright (c) 2005, Best Practical Solutions, LLC. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See L<perlartistic>. =head1 DISCLAIMER OF WARRANTY BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. =cut 1;
From: AGENT [...] cpan.org
On Thu Jan 11 04:27:10 2007, SMUELLER wrote: Show quoted text
> > I got it to work! It's not great and uses hack after hack, but the > attached Test/HTTP/Server/Simple.pm passes its tests on win32. >
Yes, with this .pm file, all the tests of Test::HTTP::Server::Simple 0.03 pass on my WinXP machine. Thanks! Unfortunately I still can't get Jifty's test suite working with this module: t/08-client..............................ok 1/4DBD::SQLite::db prepare failed: handle 2 is owned by thread 348b4 not current thread 391a6ec (handles can't be shared between threads and your driver may need a CLONE method added) at E:/Perl/site/lib/Jifty/DBI/Handle.pm line 445. Changing the DBI driver to Pg doesn't help either. I'm getting exactly the same error message: t/08-client....ok 3/4DBD::Pg::db prepare failed: handle 2 is owned by thread 3483c not current thread 40f284c (handles can't be shared between threads and your driver may need a CLONE method added) at E:/Perl/site/lib/Jifty/DBI/Handle.pm line 445. Maybe it's a problem on the Jifty::DBI side? Cheers, Agent
Patch from SMUELLER applied and released as 0.04.