hma has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks,

I released my second module, Biblio::Refbase, to CPAN on Sunday.

I've got now the first CPAN Testers error reports with a quite surprising result. The one of all tests failing is the standard pod-coverage test on some Perl 5.10 environments.

Currently I've got 6 fails (all 5.10) and 42 passes (12 passes on 5.10).(see at CPAN Testers)

I could reproduce the error on Strawberry Perl 5.10 and ActiveState Perl 5.10 on Windows: Perl just crashes when I run t/06-pod-coverage.

I tracked down the location of the crash and the situation when it happens. I use constant in my module and have some index($string, CONSTANT) calls in my code. Pod::Coverage uses Devel::Symdump to walk the symbol tree, which lets Perl crash in the moment it takes action on one of the constants I use as parameter to the index function (my other use of constants makes no problems).

I've prepared a code snippet that simulates the situation I think my module enters.

Here's the code:

use Devel::Symdump; my $x = Mod::idx('some string'); print "x=$x\n"; # works, x=5 my $obj = Devel::Symdump->new('Mod'); # crash on 5.10 package Mod; use constant 'STRING' => 'string'; sub idx { my $s = shift; return index($s, STRING); }

The crash happens in Devel::Symdump (version 2.08, line 55), where this code is executed:

local(*ENTRY) = $val;

If I print $val it reads: GLOB(0x1fa64e4)

Further investigation lead me to constant.pm (1.17, line 106):

if ($symtab && !exists $symtab->{$name}) { # No typeglob yet, so we can use a reference as space- # efficient proxy for a constant subroutine # The check in Perl_ck_rvconst knows that inlinable # constants from cv_const_sv are read only. So we have to: Internals::SvREADONLY($scalar, 1); $symtab->{$name} = \$scalar; mro::method_changed_in($pkg); } else { *$full_name = sub () { $scalar }; }

As far as I can tell this is an optimization in 5.10.

If I change the if-condition (0 && $symtab ...) to force the "else" branch, the crash does not happen.

$val then reads: *Mod::STRING

Lucky me, I found a solution for my module. Of course I didn't want to remove pod-coverage from the test suite (and I didn't want to switch to Readonly or plain variables or to use a regex instead of index). If I force the constant into scalar context, it works, too:

index($s, scalar STRING)

$val then reads (with unmodified constant.pm): SCALAR(0x1fa65ec)

I replaced the constant in index() with a simple function showing the state of wantarray(). I think the context is always scalar, so using scalar() should make no difference. But it does in the situation above!?

At this point I came to the edge of my knowledge and decided to head for the wisdom of the monks (I've been registered here for more than a year but never posted something until now. But I've read many, many marvellous posts. Thanks, monks!)

I'm very interested in some explanation or direction to the source of some explanation.

And then, if the problem I encountered is a bug (I think so), I would like advice whom to tell.

My assumptions (in descending order): It's a bug in

Thanks in advance,
Henning Manske

Replies are listed 'Best First'.
Re: constant.pm + index() + Pod::Coverage crashes on Perl 5.10
by Anonymous Monk on Dec 18, 2015 at 10:16 UTC
    Hi Henning, Perl-Monks,

    we just encountered the same problem. I think it's a bug in the Perl compiler as constant.pm does not do anything illegal concerning the symbol table.

    And just compiling the index function should not have an effect of the contents of the symbol table.

    Here's a short script to verify the error. Also includes a Workaround to use the "&" prefix for the constant when used inside the index call.

    #!/usr/bin/perl use strict; use warnings; use constant ABC => 'abc'; use constant CDE => 'cde'; use Data::Dumper; # print the constants value before the sub below has been compiled # results in $VAR1 = 'abc' BEGIN { print Dumper( ABC ); print Dumper( CDE ); } # this is in a sub to show that it's not necessary # to actually call index to change the constants behaviour sub some1 { index( shift, ABC ) }; # prefixing the constant with an "&" prevents the error sub some2 { index( shift, &CDE ) }; # print the constants value after sub some has beenn compiled # results in $VAR1 = *bc; print Dumper( ABC ); print Dumper( CDE );
    We don't use index a lot, but would be nice to see this fixed. Cheers, Stefan Riss

      For which Perl version do you get these results? When I run your program on Perl 5.20, I get the following output, which is what I expect:

      c:\Users\Corion\Projekte>perl -w tmp.pl $VAR1 = 'abc'; $VAR1 = 'cde'; $VAR1 = 'abc'; $VAR1 = 'cde';

      If you're waiting for a bug to be fixed for Perl 5.10, just upgrade to something newer. According to perlpolicy, Perl 5.10 is out of support since at least 2011.

        Hi Corion, much appreciate you looking into this. Sorry for not attaching the Perl version. This is indeed 5.10 and yes I can confirm that it has been fixed somewhere between 5.14.2 and 5.18.1 which are the versions currently available to me. We are in the process of upgrading the hardware and Perl with it ;), so it's good to know that this has been fixed. Thanks again. Best regards, Stefan