Skip Menu |

This queue is for tickets about the Error CPAN distribution.

Report information
The Basics
Id: 21080
Status: resolved
Priority: 0/
Queue: Error

People
Owner: leonerd-cpan [...] leonerd.org.uk
Requestors: alexchorny [...] gmail.com
Cc:
AdminCc:

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



Subject: 08warndie.t error on Win32
Error 0.17002. Win32 perl cannot execute open( my $childh, "-|" ). Simple solution is to skip this test on Wondows, as warndie code should be platform-independent. Long and complex solution - perlfork.pod, pipe_from_fork in 'CAVEATS AND LIMITATIONS'. ------- Alexandr Ciornii, http://chorny.net
On Sat Aug 19 10:59:10 2006, alexchorny@gmail.com wrote: Show quoted text
> Win32 perl cannot execute open( my $childh, "-|" ). Simple solution is > to skip this test on Wondows, as warndie code should be > platform-independent. > Long and complex solution - perlfork.pod, pipe_from_fork in 'CAVEATS AND > LIMITATIONS'.
OK.. well, that workaround given in the manpage would be sufficient, I believe, to let this run on Win32. I don't have access to a Win32 machine, but perhaps if I supply you an altered 08warndie.t file on his ticket, you could try it out and let me know if it works there? I know it could skip the test, but it's nice to have these things tested where possible. I don't mind a slightly messy test script if it means we do at least have good coverage. -- Paul Evans
On Sat Aug 19 10:59:10 2006, alexchorny@gmail.com wrote: Show quoted text
> Win32 perl cannot execute open( my $childh, "-|" ). Simple solution is > to skip this test on Wondows, as warndie code should be > platform-independent. > Long and complex solution - perlfork.pod, pipe_from_fork in 'CAVEATS AND > LIMITATIONS'.
Please try replacing t/08warndie.t with the version attached in this message, and let me know if it works there. It works fine for me here on Linux. If it's OK on Win32, I'll replace that in-source. -- Paul Evans
#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 21; use Error qw/ :warndie /; # Turn on full stack trace capture $Error::Debug = 1; # Returns the line number it is called from sub this_line() { my @caller = caller(); return $caller[2]; } # This file's name - for string matching my $file = $0; # Most of these tests are fatal, and print data on STDERR. We therefore use # this testing function to run a CODEref in a child process and captures its # STDERR and note whether the CODE block exited my ( $s, $felloffcode ); my $linekid = this_line + 14; # the $code->() is 14 lines below this one sub run_kid(&) { my ( $code ) = @_; # Win32's fork() emulation can't correctly handle the open("-|") case yet # So we'll implement this manually - inspired by 'perldoc perlfork' pipe my $childh, my $child or die "Cannot pipe() - $!"; defined( my $kid = fork() ) or die "Cannot fork() - $!"; if ( !$kid ) { close $childh; open(STDERR, ">&=" . fileno($child)) or die; $code->(); print STDERR "FELL OUT OF CODEREF\n"; exit(1); } close $child; $s = ""; while( defined ( $_ = <$childh> ) ) { $s .= $_; } close( $childh ); $felloffcode = 0; if( $s =~ s/FELL OUT OF CODEREF\n$// ) { $felloffcode = 1; } } ok(1, "Loaded"); run_kid { print STDERR "Print to STDERR\n"; }; is( $s, "Print to STDERR\n", "Test framework STDERR" ); is( $felloffcode, 1, "Test framework felloffcode" ); my $line; $line = this_line; run_kid { warn "A warning\n"; }; my ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^A warning at $file line $linea: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "warn \\n-terminated STDERR" ); is( $felloffcode, 1, "warn \\n-terminated felloffcode" ); $line = this_line; run_kid { warn "A warning"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^A warning at $file line $linea: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "warn unterminated STDERR" ); is( $felloffcode, 1, "warn unterminated felloffcode" ); $line = this_line; run_kid { die "An error\n"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^ Unhandled perl error caught at toplevel: An error Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "die \\n-terminated STDERR" ); is( $felloffcode, 0, "die \\n-terminated felloffcode" ); $line = this_line; run_kid { die "An error"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^ Unhandled perl error caught at toplevel: An error Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "die unterminated STDERR" ); is( $felloffcode, 0, "die unterminated felloffcode" ); $line = this_line; run_kid { throw Error( -text => "An exception" ); }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^ Unhandled exception of type Error caught at toplevel: An exception Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "Error STDOUT" ); is( $felloffcode, 0, "Error felloffcode" ); # Now custom warn and die functions to ensure the :warndie handler respects them $SIG{__WARN__} = sub { warn "My custom warning here: $_[0]" }; $SIG{__DIE__} = sub { die "My custom death here: $_[0]" }; # First test them $line = this_line; run_kid { warn "A warning"; }; $linea = $line + 2; is( $s, "My custom warning here: A warning at $file line $linea.\n", "Custom warn test STDERR" ); is( $felloffcode, 1, "Custom warn test felloffcode" ); $line = this_line; run_kid { die "An error"; }; $linea = $line + 2; is( $s, "My custom death here: An error at $file line $linea.\n", "Custom die test STDERR" ); is( $felloffcode, 0, "Custom die test felloffcode" ); # Re-install the :warndie handlers import Error qw( :warndie ); $line = this_line; run_kid { warn "A warning\n"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^My custom warning here: A warning at $file line $linea: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "Custom warn STDERR" ); is( $felloffcode, 1, "Custom warn felloffcode" ); $line = this_line; run_kid { die "An error"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^My custom death here: Unhandled perl error caught at toplevel: An error Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "Custom die STDERR" ); is( $felloffcode, 0, "Custom die felloffcode" ); # Done
From: Alexandr Ciornii <alexchorny [...] gmail.com>
On Aug 20 12:51:20 2006, PEVANS wrote: Show quoted text
> Please try replacing t/08warndie.t with the version attached in this > message, and let me know if it works there.
I've already tried this. I've slightly modified your test (added some comments ang $s output). t/08warndie....1..21 ok 1 - Loaded Print to STDERR FELL OUT OF CODEREF Filehandle GEN0 opened only for output at t/08warndie.t line 69: main::run_kid('CODE(0x197705c)') called at t/08warndie.t line 85 #$s= not ok 2 - Test framework STDERR # Failed test 'Test framework STDERR' # in t/08warndie.t at line 87. # got: '' # expected: 'Print to STDERR # ' not ok 3 - Test framework felloffcode # Failed test 'Test framework felloffcode' # in t/08warndie.t at line 88. # got: '0' # expected: '1' Filehandle GEN1 opened only for output at t/08warndie.t line 69: main::run_kid('CODE(0x1977194)') called at t/08warndie.t line 95 and so on... ------- Alexandr Ciornii, http://chorny.net
#!/usr/bin/perl -w use strict; use warnings; use Test::More tests => 21; use Error qw/ :warndie /; # Turn on full stack trace capture $Error::Debug = 1; # Returns the line number it is called from sub this_line() { my @caller = caller(); return $caller[2]; } # This file's name - for string matching my $file = $0; # Most of these tests are fatal, and print data on STDERR. We therefore use # this testing function to run a CODEref in a child process and captures its # STDERR and note whether the CODE block exited my ( $s, $felloffcode ); my $linekid = this_line + 14; # the $code->() is 14 lines below this one sub run_kid(&) { my ( $code ) = @_; sub pipe_to_fork ($) { my $parent = shift; pipe my $child, $parent or die; #pipe READHANDLE,WRITEHANDLE my $pid = fork(); die "fork() failed: $!" unless defined $pid; if ($pid) { #parent close $child; } else { #child close $parent; open(STDIN, "<&=" . fileno($child)) or die; } $pid; } use Symbol; my $childh=gensym; my $kid = pipe_to_fork($childh); defined $kid or die "Can't pipe/fork myself - $!"; if ( !$kid ) { #child close STDERR; open STDERR, ">&STDOUT"; $code->(); print STDERR "FELL OUT OF CODEREF\n"; exit(1); } #parent $s = ""; while( defined ( $_ = <$childh> ) ) { $s .= $_; } close( $childh ); $felloffcode = 0; if( $s =~ s/FELL OUT OF CODEREF\n$// ) { $felloffcode = 1; } } ok(1, "Loaded"); run_kid { print STDERR "Print to STDERR\n"; }; print "#\$s=$s\n"; is( $s, "Print to STDERR\n", "Test framework STDERR" ); is( $felloffcode, 1, "Test framework felloffcode" ); my $line; $line = this_line; run_kid { warn "A warning\n"; }; my ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^A warning at $file line $linea: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "warn \\n-terminated STDERR" ); is( $felloffcode, 1, "warn \\n-terminated felloffcode" ); $line = this_line; run_kid { warn "A warning"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^A warning at $file line $linea: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "warn unterminated STDERR" ); is( $felloffcode, 1, "warn unterminated felloffcode" ); $line = this_line; run_kid { die "An error\n"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^ Unhandled perl error caught at toplevel: An error Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "die \\n-terminated STDERR" ); is( $felloffcode, 0, "die \\n-terminated felloffcode" ); $line = this_line; run_kid { die "An error"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^ Unhandled perl error caught at toplevel: An error Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "die unterminated STDERR" ); is( $felloffcode, 0, "die unterminated felloffcode" ); $line = this_line; run_kid { throw Error( -text => "An exception" ); }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^ Unhandled exception of type Error caught at toplevel: An exception Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "Error STDOUT" ); is( $felloffcode, 0, "Error felloffcode" ); # Now custom warn and die functions to ensure the :warndie handler respects them $SIG{__WARN__} = sub { warn "My custom warning here: $_[0]" }; $SIG{__DIE__} = sub { die "My custom death here: $_[0]" }; # First test them $line = this_line; run_kid { warn "A warning"; }; $linea = $line + 2; is( $s, "My custom warning here: A warning at $file line $linea.\n", "Custom warn test STDERR" ); is( $felloffcode, 1, "Custom warn test felloffcode" ); $line = this_line; run_kid { die "An error"; }; $linea = $line + 2; is( $s, "My custom death here: An error at $file line $linea.\n", "Custom die test STDERR" ); is( $felloffcode, 0, "Custom die test felloffcode" ); # Re-install the :warndie handlers import Error qw( :warndie ); $line = this_line; run_kid { warn "A warning\n"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^My custom warning here: A warning at $file line $linea: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "Custom warn STDERR" ); is( $felloffcode, 1, "Custom warn felloffcode" ); $line = this_line; run_kid { die "An error"; }; ( $linea, $lineb ) = ( $line + 2, $line + 3 ); like( $s, qr/^My custom death here: Unhandled perl error caught at toplevel: An error Thrown from: $file:$linea Full stack trace: \tmain::__ANON__\(\) called at $file line $linekid \tmain::run_kid\('CODE\(0x[0-9a-f]+\)'\) called at $file line $lineb $/, "Custom die STDERR" ); is( $felloffcode, 0, "Custom die felloffcode" ); # Done
On Sun Aug 20 17:15:56 2006, alexchorny@gmail.com wrote: Show quoted text
> I've already tried this. I've slightly modified your test (added some > comments ang $s output).
<snip> I've altered that script further with the assistence of some Win32 people on #perl on FreeNode, and I believe what's now in 0.17003 should work for you. I've had reports of successes from others. This URL isn't live yet, but keep an eye on it and hopefully it'll be around soon, when CPAN updates its lists... http://search.cpan.org/~pevans/Error-0.17003/ -- Paul Evans
From: Alexandr Ciornii <alexchorny [...] gmail.com>
On Aug 20 17:47:12 2006, PEVANS wrote: Show quoted text
> I've altered that script further with the assistence of some Win32 > people on #perl on FreeNode, and I believe what's now in 0.17003 should > work for you. I've had reports of successes from others.
It hangs after test 1, in while cycle: while( defined ( $_ = <$childh> ) ) { $s .= $_; } Added close STDERR; after print STDERR "FELL OUT OF CODEREF\n"; Does not help. ------- Alexandr Ciornii, http://chorny.net
On Sun Aug 20 19:03:05 2006, alexchorny@gmail.com wrote: Show quoted text
> It hangs after test 1, in while cycle: > while( defined ( $_ = <$childh> ) ) { > $s .= $_; > }
I have just tried a test in Windows, using ActivePerl 5.8. I added this line within the while loop: print "Got line from child: $_"; And it would seem that we receive all the lines from the child as we're expecting, but then when the child closes the pipe and exits, our <> doesn't return undef. It just stays blocked. So I suspect in Win32 we need a new way to detect when the child has exited... Maybe we could try to kill( $kid, 0 ) it and see if it's still alive? I'll test it.... -- Paul Evans
From: leonerd-cpan [...] leonerd.org.uk
On Sun Aug 20 19:03:05 2006, alexchorny@gmail.com wrote: Show quoted text
> On Aug 20 17:47:12 2006, PEVANS wrote:
> > I've altered that script further with the assistence of some Win32 > > people on #perl on FreeNode, and I believe what's now in 0.17003 should > > work for you. I've had reports of successes from others.
> > It hangs after test 1, in while cycle: > while( defined ( $_ = <$childh> ) ) { > $s .= $_; > } > > Added > close STDERR; > after > print STDERR "FELL OUT OF CODEREF\n"; > Does not help. > > ------- > Alexandr Ciornii, http://chorny.net
OKay.... After a long amount of fiddling and chatting with people on IRC, I believe I now have a fix. The problem apparently was that STDERR needs to be closed before it is re-opened: close $childh; close STDERR; open(STDERR, ">&=" . fileno($child)) or die; That's now done, and some other small updates, in: http://search.cpan.org/~pevans/Error-0.17004/ With any luck that should now fix it. -- Paul Evans
From: Geoff Simmons <gsimmons [...] cpan.org>
On Fri Sep 01 19:14:43 2006, PEVANS wrote: Show quoted text
> That's now done, and some other small updates, in: > > http://search.cpan.org/~pevans/Error-0.17004/ > > With any luck that should now fix it.
I can confirm that t/08warndie.t has passed successfully on a Win32 platform (Windows XP SP2), with ActivePerl 5.8.8 Build 817.
From: Alexandr Ciornii <alexchorny [...] gmail.com>
On Sep 02 04:49:52 2006, GSIMMONS wrote: Show quoted text
> I can confirm that t/08warndie.t has passed successfully on a Win32 > platform (Windows XP SP2), with ActivePerl 5.8.8 Build 817.
Works for me also. ActiveState 5.8.7 and Vanilla 5.8.8.
Then I guess I can put this one to bed, and say it's now sorted. -- Paul Evans