wu-lee has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I've been trying to put breakpoints in a Test::Class derivative's test method. The debugger lists the breakpoint, but never stops there. I've whittled this down, and I think it may be due to the attributes used to label test methods.

Is this a bug in the debugger? Either way, is there a workaround? I can't put a breakpoint in a file which isn't the current file, otherwise I could specify the right line to break on.

Consider this example program:

package X; use strict; use Attribute::Handlers; sub a : ATTR(SCALAR) { print "a\n"; } sub b { print "b\n"; } package main; X::a; X::b;
Then if I debug this I get the same sort of behaviour described above. i.e. The breakpoint on subroutine a (with the attribute) is ignored, and the debugger stops instead on subroutine b (with no attributes). Listing the breakpoints, the debugger seems to have put b's breakpoint on an unbreakable line:
$ perl -d dbtest.pl Loading DB routines from perl5db.pl version 1.28 Editor support available. Enter h or `h h' for help, or `man perldebug' for more help. Attribute::Handlers::CODE(0x8322008)(/usr/share/perl/5.8/Attribute/Han +dlers.pm:206): 206: $global_phase++; DB<1> printf "Perl v%vd\n", $^V Perl v5.8.8 DB<2> b X::a DB<3> b X::b DB<4> L dbtest.pl: 5: sub a : ATTR(SCALAR) { break if (1) 10: print "b\n"; break if (1) DB<4> c a X::b(dbtest.pl:10): print "b\n"; DB<4>

Replies are listed 'Best First'.
Re: bug in the debugger? breakpoints in subroutines ignored if attributes present
by RMGir (Prior) on Apr 23, 2007 at 13:36 UTC
    I tested in 5.8.7, not 5.8.8, but I saw the same results. I tested a few other things about X::a, but I can't see why the debugger gets confused.

    One clue as to what's going on might be in the perl -MO=Deparse output:

    package X; sub BEGIN { require strict; do { 'strict'->import }; } use Attribute::Handlers; sub a { use strict 'refs'; print "a\n"; } use attributes ('X', sub { use strict 'refs'; print "a\n"; } , 'ATTR(SCALAR)'); sub b { use strict 'refs'; print "b\n"; } package main; use strict 'refs'; X::a(); X::b();
    The use attributes after sub a is interesting. If it reassigned *X::a that could explain weird behaviour, but it doesn't. Interesting!

    Adding a call to a routine that prints "caller" info instead of the print statements in a and b shows that the caller info is sane, and matches the expected line numbers.


    Mike
      The use attributes line is there for two reasons:
      1. Loads attributes.pm if it isn't loaded.
      2. Regardless of if it was loaded, calls attributes->import( ... ) with the params passed.

      I'm willing to bet that what happens is that the breakpoint is set on the "sub a", but that function isn't executed. Instead, it is replaced by the one declared by attributes. Unfortunately, the attributes heavy lifting code is within the Perl source, so it's a little less accessible to one such as I.


      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
Re: bug in the debugger? breakpoints in subroutines ignored if attributes present (work-around)
by tye (Sage) on Apr 23, 2007 at 15:58 UTC

    Instead of "b X::a", do the following:

    % perl -d test.pl # ... 206: $global_phase++; DB<1> l X::a Switching to file 'test.pl'. 5: sub a : ATTR(SCALAR) { 6: print "a\n"; 7: } DB<2> b 6 DB<3> c X::a(attribBreak.pl:6): print "a\n"; DB<3>

    - tye        

      Indeed that's the obvious solution in this case, but in the real case, the line in question is buried in some class in another file. The reason I want to breakpoint a method is because I can't put a breakpoint there using the line number, at least without stepping through lots of intervening code.

        I don't see how what you describe makes what I suggested any less useful. Instead of putting a breakpoint on a method, list the start of the method and put a breakpoint on the first line inside of the method. I certainly didn't step "though lots of intervening code" so I'm not sure why you think you would need to.

        - tye        

Re: bug in the debugger? breakpoints in subroutines ignored if attributes present
by herveus (Prior) on Apr 23, 2007 at 13:30 UTC
    Howdy!

    Using 5.8.8 on Solaris 10, I get the same results you report.

    I wonder if Attribute::Handler is interacting with the debugger in strange and wonderful ways. I don't have any particular insights on the problem.

    yours,
    Michael
Re: bug in the debugger? breakpoints in subroutines ignored if attributes present
by Moron (Curate) on Apr 23, 2007 at 15:39 UTC
    How about just moving the code inside 'a' to an attribute-free routine, wlf., and setting the breakpoint on that instead, e.g.
    sub a : ATTR(SCALAR) { _a( @_ ); } sub _a { print "a\n"; }
    M. Oron D.B.O. (Doctor in the Bl**ding obvious ;))
    __________________________________________________________________________________

    ^M Free your mind!

      Thank you, this does work. Unfortunately this makes the resulting code look like a non-sequitur, so I'm not sure I could justify it for the general case.
Re: bug in the debugger? breakpoints in subroutines ignored if attributes present
by renodino (Curate) on Apr 23, 2007 at 14:52 UTC
    I've encountered a related problem in ActiveState Perl 5.8.6 (see Re^2: Attribute confusion). I posted a bug report, but haven't pursued it further. The error msg reported there might be a clue as to the cause, tho its interesting that newer versions seem to suppress the error msgs.

    IIRC, I tried to diagnose the Attributes::Handler code, but got lost pretty quickly in some of its more arcane symbol twiddling.


    Perl Contrarian & SQL fanboy
Re: bug in the debugger? breakpoints in subroutines ignored if attributes present
by clueless newbie (Curate) on Apr 23, 2007 at 20:49 UTC
    Have you tried setting the break point by inserting $DB::single = $DB::single = 1;?
      Thanks, but no, mainly because my problem isn't so much getting the debugger to stop once, it's passing on test code which is difficult debug in general.