develooper Front page | perl.perl5.porters | Postings from December 2012

Subroutine attributes and debugging

Thread Next
From:
Paul Johnson
Date:
December 9, 2012 00:05
Subject:
Subroutine attributes and debugging
Message ID:
20121209000546.GE2999@pjcj.net
I've been tracking down a bug report in Devel::Cover and I think it's
pointing to a bug in perl.  The original bug report is
https://github.com/pjcj/Devel--Cover/issues/38 and I have narrowed the
problem down to the following code:

    my $attributed;
    sub MODIFY_CODE_ATTRIBUTES {
        my ($class, $code, @attrs) = @_;
        $attributed = $code;
        return;
    }
    my $foo = sub :MyAttribute {};
    print "$attributed, $foo\n";

If you run this code normally, you find that $attributed and $foo have
the same value.  This is as it should be since the docs for
attributes.pm say that $code should be a reference to the sub with the
attribute.  (Actually, the docs don't explicitly say that but I think
the intent is clear.)

When run under the debugger you find that $code is actually a different
subroutine reference.  The reason is this little bit of code in
pad.c:1727:

    if (PL_cv_has_eval || PL_perldb) {
        const CV *cv;
        for (cv = PL_compcv ;cv; cv = CvOUTSIDE(cv)) {
            if (cv != PL_compcv && CvCOMPILED(cv))
                break; /* no need to mark already-compiled code */
            if (CvANON(cv)) {
                DEBUG_Xv(PerlIO_printf(Perl_debug_log,
                    "Pad clone on cv=0x%"UVxf"\n", PTR2UV(cv)));
                CvCLONE_on(cv);
            }
            CvHASEVAL_on(cv);
        }
    }

The code is preceded by this comment:

    /* If this CV has had any 'eval-capable' ops planted in it
     * (ie it contains eval '...', //ee, /$var/ or /(?{..})/), Then any
     * anon prototypes in the chain of CVs should be marked as cloneable,
     * so that for example the eval's CV in C<< sub { eval '$x' } >> gets
     * the right CvOUTSIDE.
     * If running with -d, *any* sub may potentially have an eval
     * executed within it.
     */

So, there are a few questions.

First, is it correct that these two subroutine refs should be identical?

If so, should that also hold when running under the debugger?

And if it shouldn't necessarily hold, is that also true for $^P being
set to any value, as is currently the case?

The reason this shows up in Devel::Cover is because $^P is set to 0x104
which, I think, doesn't meet the conditions in the comment.

Perhaps one other note of interest is the comment before the
Perl_pad_tidy subroutine:

    /* XXX DAPM surely most of this stuff should be done properly
     * at the right time beforehand, rather than going around afterwards
     * cleaning up our mistakes ???
     */

Opinions?

-- 
Paul Johnson - paul@pjcj.net
http://www.pjcj.net

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About