Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Test-TCP CPAN distribution.

Report information
The Basics
Id: 66437
Status: resolved
Priority: 0/
Queue: Test-TCP

People
Owner: Nobody in particular
Requestors: bo.johansson [...] lsn.se
Cc:
AdminCc:

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



Subject: Tests are blocking in Windows 7
I am using: * Strawberry-perl-5.12.2.0 * Perl 5, version 12, subversion 2 (v5.12.2) built for MSWin32-x86-multi-thread * Windows 7 Home Premium with Service Pack 1 I have used version 1.11 and 1.12 of Test::TCP Problem: The test in Test::TCP is blocking. Get the system in state, that it must be restarted. It is sometimes not possible to kill the blocked processes. I even get errors like “Can't spawn "cmd.exe"” when using the system call. It indicates a degeneration of the perl interpreter. Tries and errors: I have tried a lot of changes and also tried to find out what the real problem is. But i have not succeeded. Probably there is a problem in the emulation of fork in Windows. I have found by adding "sleep 1;" in some places there is an improvement. I think that it is not the delay, but that it cause a "context change" in the fork emulation that is important. I have also tried to add a "sleep 1;" in the destructor. It gives some improvements but is not enough. sub DESTROY { my $self = shift; local $@; sleep 1; #added gives some improvement $self->stop(); } In several tests it is necessary to add an explicit shutdown of the server t::Server->new($port)->run(sub { note "new request"; my ($remote, $line, $sock) = @_; + if ($line eq "quit\n"){ + exit 0; + }; print {$remote} $line; }); }, An alternative is to make test_tcp to return the $server. sub test_tcp { ..... $args{client}->($server->port, $server->pid); #undef $server; # make sure REMOVED return $server; # ADDED } This makes it possible to do the shout down in the tests in this way my $object = test_tcp .... $object->stop; Using the object oriented way of calling this technique can be used In t/10_oo.t I have done the changes: -print {$sock} "quit\n"; +$server->stop; Patch with proposed changes: diff -u -r t.orig/01_simple.t t/01_simple.t --- t.orig/01_simple.t 2010-08-15 16:21:39.000000000 +0200 +++ t/01_simple.t 2011-03-06 20:04:45.875400000 +0100 @@ -27,6 +27,7 @@ note "finalize"; print {$sock} "quit\n"; + sleep 1; }, server => sub { my $port = shift; @@ -34,8 +35,13 @@ t::Server->new($port)->run(sub { note "new request"; my ($remote, $line, $sock) = @_; + if ($line eq "quit\n"){ + exit 0; + }; print {$remote} $line; }); }, ); +warn $$; + diff -u -r t.orig/08_exit.t t/08_exit.t --- t.orig/08_exit.t 2010-08-24 07:08:16.000000000 +0200 +++ t/08_exit.t 2011-03-06 20:06:41.907000000 +0100 @@ -37,6 +37,7 @@ client => sub { my $port = shift; note "CLIENT: $$"; + sleep 1; exit 1; }, server => sub { @@ -53,3 +54,4 @@ ); } + diff -u -r t.orig/09_fork.t t/09_fork.t --- t.orig/09_fork.t 2011-03-03 09:13:54.000000000 +0100 +++ t/09_fork.t 2011-03-06 22:31:39.035000000 +0100 @@ -39,12 +39,20 @@ print {$sock} "Hello server\n"; my $res = <$sock>; is $res, "Hello server\n", "got expected reply"; + + note "finalize"; + print {$sock} "quit\n"; + sleep 1; + warn "Client exit after sleep $$"; }, server => sub { my $port = shift; t::Server->new($port)->run(sub { note "new request"; my ($remote, $line, $sock) = @_; + if ($line eq "quit\n"){ + exit 0; + }; print {$remote} $line; }); } @@ -56,3 +64,5 @@ diag "test_tcp() leaks \$?. Maybe it's Perl bug?: $?"; $? = 0; } + + diff -u -r t.orig/10_oo.t t/10_oo.t --- t.orig/10_oo.t 2011-03-03 09:13:56.000000000 +0100 +++ t/10_oo.t 2011-03-07 07:37:18.063200000 +0100 @@ -35,7 +35,7 @@ is $res2, "bar\n"; note "finalize"; -print {$sock} "quit\n"; +$server->stop; if ($?) { # It's maybe ActivePerl's bug.
Same here. Tests hang in Windows 7 using Strawberry Perl. I am willing to provide additional info upon request.
I can not reproduce the problem. Using: Windows 7 Professional with SP1 (running under VMware) StrawberryPerl-5.12.1 with bundled dmake/MinGW ActivePerl-5.12.1.1201 with nmake/vc6 On ActivePerl I get the wrong exit code for some tests (bug #66016), but if I add the sleep(1) call at the end of the stop() function, then all tests pass under both Perl distributions. I've been running `dmake test` 5 times, all "PASS". Anything else that has to be done to make it crash/hang? BTW, I'm running manually from the commandline, not using cpan/cpanplus/cpanm.
From: bo.johansson [...] lsn.se
Vid Thu, 10 Mar 2011 kl. 14.54.38, skrev JDB: Show quoted text
> I can not reproduce the problem.
The test are still blocking for me. The proposed modification makes a significant improvment for the 08_exit.t test. It is blocking, but first after about a 10 to 150 times. (Using a batch file like this below, which is only calling perl -Ilib t/08_exit.t.) When using the batchfile below, I got the following result in 10 tries: c 8 t01; c 6 t08; c 2 t01; c 6 t10; c 6 t10; c 7 t01; c 6 t10; c 30 t01; c 12 t10; c 3 t10 The figure after c means blocking in loop number and txx indicates the test which is blocking. Used batch file: @echo off set count=0 :loop set /a count=%count%+1 echo Count %count% @echo on perl -Ilib t/01_simple.t perl -Ilib t/08_exit.t perl -Ilib t/09_fork.t perl -Ilib t/10_oo.t @echo off goto loop I am using: * Test::TCP $VERSION = '1.12'; with the added line see below. * Strawberry-perl-5.12.2.0 * Perl 5, version 12, subversion 2 (v5.12.2) built for MSWin32-x86-multi-thread * Windows 7 Home Premium with Service Pack 1 sub stop { my $self = shift; .... undef $self->{pid}; sleep(1) if $^O eq "MSWin32"; #added line }
Subject: Proposal for making modules using fork more portable
From: bo.johansson [...] lsn.se
Proposal for making modules using fork more portable PROPOSAL To add an advice to explicitly shut down child processes by the implementation of modules intended to be portable. The purpose with this is to avoid the related problem in the emulation of fork in Windows. In the documentation of fork there could be a warning about the problem and an reference to perlfork http://perldoc.perl.org/perlfork.html. In perlfork there should be an advice to explicitly shut down child processes and how to avoid using kill(9, $child). BACKGROUND Using kill(9, $child) in Windows, where fork is emulated in the perl interpreter, there is a probability to get a blocked process. Work is going on to improve the perlfork implementation in Windows (see: http://www.gossamer-threads.com/lists/perl/porters/261805), but it will take a long time until the new versions of Perl are used in all places. To update a module is often done faster. Example of problem: The test in Test::TCP is blocking. Get the system in state, that it must be restarted. It is sometimes not possible to kill the blocked processes. I even get errors like “Can't spawn "cmd.exe"” when using the system call. It indicates a degeneration of the perl interpreter. I am using: * Strawberry-perl-5.12.2.0 * Perl 5, version 12, subversion 2 (v5.12.2) built for MSWin32-x86-multi-thread * Windows 7 Home Premium with Service Pack 1 From http://perldoc.perl.org/perlfork.html: On some platforms such as Windows where the fork() system call is not available, Perl can be built to emulate fork() at the interpreter level. While the emulation is designed to be as compatible as possible with the real fork() at the level of the Perl program, there are certain important differences that stem from the fact that all the pseudo child "processes" created this way live in the same real process as far as the operating system is concerned. Jan Dubois wrote in https://rt.cpan.org/Public/Bug/Display.html?id=66016#txn-910239 Note though that kill(9, $child) is inherently unsafe for pseudo-processes. ... Here is the list of warnings about some of the things that can go wrong if you call TerminateThread() when you don't know the current state of the thread (from the Microsoft docs): * If the target thread owns a critical section, the critical section will not be released. * If the target thread is allocating memory from the heap, the heap lock will not be released. * If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent. * If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL. As the terminated thread runs inside the same process as the controlling thread, it is always possible that the controlling thread will get damaged by this action. … Anyway, I don't think TerminateThread() can ever be completely safe if you call it when the child thread may not be in a wait state, so I hope the alternate implementation will solve the issue instead (for 5.14 and later only, for 5.12 and earlier we will have to add the sleep() calls and live with the occasional breakage, I think).
I hope the issue was resolved by latest release.