Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Package-Stash-XS CPAN distribution.

Report information
The Basics
Id: 74151
Status: open
Priority: 0/
Queue: Package-Stash-XS

People
Owner: Nobody in particular
Requestors: paul [...] city-fan.org
Cc: ribasushi [...] leporine.io
AdminCc:

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



Subject: Incompatibility with perl <= 5.8.6 and Test::Without::Module
When trying to build Class::Load 0.13 on a system with an old perl (this seems to manifest with perl <= 5.8.6 and not with perl >= 5.8.8), the test suite runs some implementation tests, using Test::Without::Module to inhibit normally-preferred implementations from loading. The test suite fails such tests, like this: t/011-without-xs................Package::Stash::XS is not a module name at /usr/lib/perl5/vendor_perl/5.8.5/Package/Stash.pm line 40. BEGIN failed--compilation aborted at /usr/lib/perl5/vendor_perl/5.8.5/Package/Stash.pm line 46. Compilation failed in require at /builddir/build/BUILD/Class-Load-0.13/blib/lib/Class/Load.pm line 15. BEGIN failed--compilation aborted at /builddir/build/BUILD/Class-Load-0.13/blib/lib/Class/Load.pm line 15. Compilation failed in require at t/011-without-xs.t line 14. # Looks like your test died before it could output anything. dubious Test returned status 255 (wstat 65280, 0xff00) DIED. FAILED test 1 Failed 1/1 tests, 0.00% okay t/012-without-implementation....# Failed test (t/012-without-implementation.t at line 14) # 'Package::Stash::XS is not a module name at /usr/lib/perl5/vendor_perl/5.8.5/Package/Stash.pm line 40. # BEGIN failed--compilation aborted at /usr/lib/perl5/vendor_perl/5.8.5/Package/Stash.pm line 46. # Compilation failed in require at /builddir/build/BUILD/Class-Load-0.13/blib/lib/Class/Load.pm line 15. # BEGIN failed--compilation aborted at /builddir/build/BUILD/Class-Load-0.13/blib/lib/Class/Load.pm line 15. # Compilation failed in require at t/012-without-implementation.t line 13. # ' # doesn't match '(?-xism:Class.Load.PP\.pm did not return a true value)' # Looks like you failed 1 tests of 1. dubious Test returned status 1 (wstat 256, 0x100) DIED. FAILED test 1 Failed 1/1 tests, 0.00% okay Digging around a bit, this appears to be an incompatibility between Package::Stash::XS and Test::Without::Module on these old perls: * Using Test::Without::Module and *any* module name provokes the error * The Package::Stash test suite breaks in the presence of Test::Without::Module on old perls if the implementation is XS but not if it's pure perl * The attached test is basically a copy of Package::Stash::XS's t/get.t but with Test::Without::Module loaded, and it fails on old perls I don't know if the problem here is really in Package::Stash::XS or Test::Without::Module, but I think the former is more likely so that's why I'm raising it here. Of course you might decide that supporting such ancient perls isn't worth it but I don't know if I don't ask... (the test output above is from CentOS 4.9 x86_64 if that's any help)
Subject: get-with-test-without-module.t
#!/usr/bin/env perl use strict; use warnings; use lib 't/lib'; use Test::More tests => 36; use Test::Without::Module 'Completely::Unrelated::Module'; use Package::Stash; use Scalar::Util; { BEGIN { my $stash = Package::Stash->new('Hash'); my $val = $stash->get_symbol('%foo'); is($val, undef, "got nothing yet"); } { no warnings 'void', 'once'; %Hash::foo; } BEGIN { my $stash = Package::Stash->new('Hash'); my $val = $stash->get_symbol('%foo'); is(ref($val), 'HASH', "got something"); $val->{bar} = 1; is_deeply($stash->get_symbol('%foo'), {bar => 1}, "got the right variable"); is_deeply(\%Hash::foo, {bar => 1}, "stash has the right variable"); } } { BEGIN { my $stash = Package::Stash->new('Array'); my $val = $stash->get_symbol('@foo'); is($val, undef, "got nothing yet"); } { no warnings 'void', 'once'; @Array::foo; } BEGIN { my $stash = Package::Stash->new('Array'); my $val = $stash->get_symbol('@foo'); is(ref($val), 'ARRAY', "got something"); push @$val, 1; is_deeply($stash->get_symbol('@foo'), [1], "got the right variable"); is_deeply(\@Array::foo, [1], "stash has the right variable"); } } { BEGIN { my $stash = Package::Stash->new('Scalar'); my $val = $stash->get_symbol('$foo'); is($val, undef, "got nothing yet"); } { no warnings 'void', 'once'; $Scalar::foo; } BEGIN { my $stash = Package::Stash->new('Scalar'); my $val = $stash->get_symbol('$foo'); is(ref($val), 'SCALAR', "got something"); $$val = 1; is_deeply($stash->get_symbol('$foo'), \1, "got the right variable"); is($Scalar::foo, 1, "stash has the right variable"); } } { BEGIN { my $stash = Package::Stash->new('Code'); my $val = $stash->get_symbol('&foo'); is($val, undef, "got nothing yet"); } { no warnings 'void', 'once'; sub Code::foo { } } BEGIN { my $stash = Package::Stash->new('Code'); my $val = $stash->get_symbol('&foo'); is(ref($val), 'CODE', "got something"); is(prototype($val), undef, "got the right variable"); &Scalar::Util::set_prototype($val, '&'); is($stash->get_symbol('&foo'), $val, "got the right variable"); is(prototype($stash->get_symbol('&foo')), '&', "got the right variable"); is(prototype(\&Code::foo), '&', "stash has the right variable"); } } { BEGIN { my $stash = Package::Stash->new('Io'); my $val = $stash->get_symbol('FOO'); is($val, undef, "got nothing yet"); } { no warnings 'void', 'once'; package Io; fileno(FOO); } BEGIN { my $stash = Package::Stash->new('Io'); my $val = $stash->get_symbol('FOO'); isa_ok($val, 'IO'); my $str = "foo"; open $val, '<', \$str; is(readline($stash->get_symbol('FOO')), "foo", "got the right variable"); seek($stash->get_symbol('FOO'), 0, 0); { package Io; ::isa_ok(*FOO{IO}, 'IO'); ::is(<FOO>, "foo", "stash has the right variable"); } } } { my $stash = Package::Stash->new('Hash::Vivify'); my $val = $stash->get_or_add_symbol('%foo'); is(ref($val), 'HASH', "got something"); $val->{bar} = 1; is_deeply($stash->get_or_add_symbol('%foo'), {bar => 1}, "got the right variable"); no warnings 'once'; is_deeply(\%Hash::Vivify::foo, {bar => 1}, "stash has the right variable"); } { my $stash = Package::Stash->new('Array::Vivify'); my $val = $stash->get_or_add_symbol('@foo'); is(ref($val), 'ARRAY', "got something"); push @$val, 1; is_deeply($stash->get_or_add_symbol('@foo'), [1], "got the right variable"); no warnings 'once'; is_deeply(\@Array::Vivify::foo, [1], "stash has the right variable"); } { my $stash = Package::Stash->new('Scalar::Vivify'); my $val = $stash->get_or_add_symbol('$foo'); is(ref($val), 'SCALAR', "got something"); $$val = 1; is_deeply($stash->get_or_add_symbol('$foo'), \1, "got the right variable"); no warnings 'once'; is($Scalar::Vivify::foo, 1, "stash has the right variable"); } { BEGIN { my $stash = Package::Stash->new('Io::Vivify'); my $val = $stash->get_or_add_symbol('FOO'); isa_ok($val, 'IO'); my $str = "foo"; open $val, '<', \$str; is(readline($stash->get_symbol('FOO')), "foo", "got the right variable"); seek($stash->get_symbol('FOO'), 0, 0); } { package Io::Vivify; no warnings 'once'; ::isa_ok(*FOO{IO}, 'IO'); ::is(<FOO>, "foo", "stash has the right variable"); } }
Since I hit this problem last year, and am now facing it again in a different module, I figured I should write down what is actually going on. The problem in its core is a state-corruption of the regex engine when used during a require() lookup. In other words on perl <= 5.8.6 any module that wraps CORE::require() OR adds a coderef to @INC, AND executes code as part of this overload that involves a re match will leave the re engine in some weird state which makes the re match executed by Package::Stash::XS[1] (invoked at [2]) fail. Unfortunately I am not aware of a way to fix this, as thre XS magic is alien to me. Will try to interest some people with the chops to look at this. Cheers! [1] https://metacpan.org/source/DOY/Package-Stash-XS-0.25/XS.xs#L207 [2] https://metacpan.org/source/DOY/Package-Stash-0.33/lib/Package/Stash.pm#L40 P.S. I worked around this before privately by using index() in my require hooks. Test::WithoutModule could potentially do the same, but it's gross, and should be last resort if we can't find a way to fix P::S::XS P.P.S. The shortest way to demonstrate the problem: rabbit@Thesaurus:~$ perl -v This is perl, v5.8.6 built for i686-linux-thread-multi rabbit@Thesaurus:~$ perl -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ /blah/; return () }; require Package::Stash::PP; print "ok\n";' ok rabbit@Thesaurus:~$ perl -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ /blah/; return () }; require Package::Stash::XS; print "ok\n";' ok rabbit@Thesaurus:~$ perl -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ /blah/; return () }; require Package::Stash; print "ok\n";' Package::Stash::XS is not a module name at /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm line 40. BEGIN failed--compilation aborted at /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm line 46. Compilation failed in require at -e line 1. rabbit@Thesaurus:~$ perl -MCarp::Always -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ /blah/; return () }; require Package::Stash; print "ok\n";' Package::Stash::XS is not a module name at /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm line 40 Package::Stash::BEGIN() called at /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm line 46 eval {...} called at /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm line 46 require Package/Stash.pm called at -e line 1 BEGIN failed--compilation aborted at /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm line 46 require Package/Stash.pm called at -e line 1 Compilation failed in require at -e line 1
On Mon Feb 13 05:29:22 2012, RIBASUSHI wrote: Show quoted text
> Since I hit this problem last year, and am now facing it again in a > different module, I figured I should write down what is actually going > on. The problem in its core is a state-corruption of the regex engine > when used during a require() lookup. In other words on perl <= 5.8.6 any > module that > > wraps CORE::require() > OR > adds a coderef to @INC, > AND > executes code as part of this overload that involves a re match > > will leave the re engine in some weird state which makes the re match > executed by Package::Stash::XS[1] (invoked at [2]) fail. Unfortunately I > am not aware of a way to fix this, as thre XS magic is alien to me. Will > try to interest some people with the chops to look at this. Cheers! > > [1] https://metacpan.org/source/DOY/Package-Stash-XS-0.25/XS.xs#L207 > [2] > https://metacpan.org/source/DOY/Package-Stash-0.33/lib/Package/Stash.pm#L40 > > P.S. I worked around this before privately by using index() in my > require hooks. Test::WithoutModule could potentially do the same, but > it's gross, and should be last resort if we can't find a way to fix P::S::XS > > P.P.S. The shortest way to demonstrate the problem: > > rabbit@Thesaurus:~$ perl -v > This is perl, v5.8.6 built for i686-linux-thread-multi > > rabbit@Thesaurus:~$ perl -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ > /blah/; return () }; require Package::Stash::PP; print "ok\n";' > ok > > rabbit@Thesaurus:~$ perl -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ > /blah/; return () }; require Package::Stash::XS; print "ok\n";' > ok > > rabbit@Thesaurus:~$ perl -e 'unshift @INC, sub { my $x = $ENV{PATH} =~ > /blah/; return () }; require Package::Stash; print "ok\n";' > Package::Stash::XS is not a module name at > /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm > line 40. > BEGIN failed--compilation aborted at > /home/rabbit/perl5/perlbrew/perls/5.8.6/lib/site_perl/5.8.6/Package/Stash.pm > line 46. > Compilation failed in require at -e line 1.
This has something to do with the way pregexec is called. I don’t actually understand its calling convention and am not about to find out. But I did discover that doing the regexp match from Perl (actually in Package::Stash before calling ::XS) works. Presumably the workaround is for ::XS do use a Perl subroutine for matching, or possibly even better, use a custom checker written in C, which would be even faster than a regexp.
On Mon Feb 13 05:29:22 2012, RIBASUSHI wrote: Show quoted text
> Since I hit this problem last year, and am now facing it again in a > different module, I figured I should write down what is actually > going on.
I have a simpler failing test case: perl -de '{ use Moose }' Package::Stash::XS is not a module name at /usr/lib/perl5/site_perl/5.8.5/Package/Stash.pm line 40. ... That is, it appears to be impossible to use the debugger with any program using Moose. This is on perl 5.8.5. Moose is up-to-date.