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

I'm trying to understand a failure in a call to a sub in Net::SSLeay. My problem is that the module is only require-d well into the script's execution. I can require the module in perldb, but that only gives me a few uninteresting subs. I know where I need to break, but perldb does not have enough information to install a breakpoint, or so it seems.

I could use print(), but I'd rather not edit the file. Or must I?

Replies are listed 'Best First'.
Re: using perldb
by LanX (Saint) on Sep 02, 2021 at 08:17 UTC
    Hi

    please try

    b compile subname Sets a breakpoint before the first statement executed +after the specified subroutine is compiled.

    or

    b postpone subname [condition] Set a breakpoint at first line of subroutine after it +is compiled.

    see perldebug for more options, like setting watch expressions on $AUTOLOAD or conditional breaks on AUTOLOAD()

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      I'm afraid I couldn't make neither b compile nor b postpone work for me, with different attempts to "compile" a new sub.

      Here my experiments using eval , a typeglob and use (applying the technique from Re: Debugger demos/snippets)

      Not sure what is going wrong ...

      Haven't tested breaking AUTOLOAD tho

      use strict; use warnings; use Data::Dump qw/pp dd/; BEGIN { push @DB::typeahead, split /\n/, <<'__DB__'; B * # delete all Breakpoints # --- these should fail b testsub1 b testsub2 b testsub3 b postpone testsub1 b compile testsub1 b postpone testsub2 b compile testsub2 b postpone testsub3 b compile testsub3 L # list breakpoints use lib '.'; use db_demo_postpone qw(testsub3); L c __DB__ # use after debug-commands # use lib '.'; # use db_demo_postpone qw(testsub3); } eval <<'__CODE__'; sub testsub1 { warn "inside testsub1"; } __CODE__ *testsub2 = sub { warn "inside testsub2"; }; warn "before"; testsub1(); warn "after1"; testsub2(); warn "after2"; testsub3(); warn "after3";

      package db_demo_postpone; use strict; use warnings; use Exporter qw(import); our @EXPORT_OK = qw(testsub3); sub testsub3 { warn "inside testsub3"; } warn "testsub3 compiled"; 1;

      OUTPUT: perl -d d:/tmp/pm/db_demo_postpone.pl

      Current directory is d:/tmp/pm/ Loading DB routines from perl5db.pl version 1.57 Editor support enabled. Enter h or 'h h' for help, or 'perldoc perldebug' for more help. auto(-23) DB<1> B * # delete all +Breakpoints Line * # delete all Breakpoints no +t breakable. auto(-22) DB<2> # --- these should fail auto(-21) DB<3> b testsub1 Subroutine main::testsub1 not found. auto(-20) DB<4> b testsub2 Subroutine main::testsub2 not found. auto(-19) DB<5> b testsub3 Subroutine main::testsub3 not found. auto(-18) DB<6> auto(-17) DB<6> b postpone testsub1 auto(-16) DB<7> b compile testsub1 auto(-15) DB<8> auto(-14) DB<8> b postpone testsub2 auto(-13) DB<9> b compile testsub2 auto(-12) DB<10> auto(-11) DB<10> b postpone testsub3 auto(-10) DB<11> b compile testsub3 auto(-9) DB<12> auto(-8) DB<12> L # list breakp +oints Postponed breakpoints in subroutines: main::testsub3 compile main::testsub1 compile main::testsub2 compile auto(-7) DB<13> auto(-6) DB<13> use lib '.'; auto(-5) DB<14> use db_demo_postpone qw(testsub3); testsub3 compiled at db_demo_postpone.pm line 13. at db_demo_postpone.pm line 13. require db_demo_postpone.pm called at (eval 17)[c:/Strawberry/perl +/lib/perl5db.pl:738] line 2 main::BEGIN() called at db_demo_postpone.pm line 0 eval {...} called at db_demo_postpone.pm line 0 eval 'no strict; ($@, $!, $^E, $,, $/, $\\, $^W) = @DB::saved;pack +age main; $^D = $^D | $DB::db_stop; use db_demo_postpone qw(testsub3);; ' called at c:/Strawberry/perl/lib/perl5db.pl line 738 DB::eval called at c:/Strawberry/perl/lib/perl5db.pl line 3138 DB::DB called at d:/tmp/pm/db_demo_postpone.pl line 45 auto(-4) DB<15> auto(-3) DB<15> L Postponed breakpoints in subroutines: main::testsub3 compile main::testsub1 compile main::testsub2 compile auto(-2) DB<15> auto(-1) DB<15> c DB<15> L Postponed breakpoints in subroutines: main::testsub3 compile main::testsub1 compile main::testsub2 compile DB<15> c before at d:/tmp/pm/db_demo_postpone.pl line 57. at d:/tmp/pm/db_demo_postpone.pl line 57. inside testsub1 at (eval 20)[d:/tmp/pm/db_demo_postpone.pl:45] line 2. at (eval 20)[d:/tmp/pm/db_demo_postpone.pl:45] line 2. main::testsub1() called at d:/tmp/pm/db_demo_postpone.pl line 59 after1 at d:/tmp/pm/db_demo_postpone.pl line 61. at d:/tmp/pm/db_demo_postpone.pl line 61. inside testsub2 at d:/tmp/pm/db_demo_postpone.pl line 52. at d:/tmp/pm/db_demo_postpone.pl line 52. main::__ANON__[d:/tmp/pm/db_demo_postpone.pl:53]() called at d:/tm +p/pm/db_demo_postpone.pl line 63 after2 at d:/tmp/pm/db_demo_postpone.pl line 65. at d:/tmp/pm/db_demo_postpone.pl line 65. inside testsub3 at db_demo_postpone.pm line 10. at db_demo_postpone.pm line 10. db_demo_postpone::testsub3() called at d:/tmp/pm/db_demo_postpone. +pl line 67 after3 at d:/tmp/pm/db_demo_postpone.pl line 69. at d:/tmp/pm/db_demo_postpone.pl line 69. DB<15>

      As you can see no break happened :/

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        I can only help with one of the cases: If you to qualify b compile db_demo_postpone::testsub3, then this particular case seems to work (because that's the name under which it is compiled). Importing it into the main namespace doesn't compile. I also would sort of expect that *testsub2 = sub {...} doesn't work, because it is compiled as an anonymous sub, and only then pushed into the symbol table. For the rest of the cases I have no clue.

        My own experience with b postpone was never very successful. For a start, there's no feedback when you mistype the subroutine or package name (and I mistype often). And then, I never found out in which cases it would actually work (or whether it has just stopped working in recent Perls).

        That's why I ended up with my brute-force method: Whenever b Foo::bar tells me that the method isn't found, I just call it and then, if the call seems to actually call something, try again. With the debugger's command history, that's even less typing than postpone.

Re: using perldb
by haj (Vicar) on Sep 02, 2021 at 06:22 UTC

    I guess you don't "see" the subroutine because Net::SSLeay uses autoloading for many of its subroutines. So what you can do is trigger the autoloading by calling the sub, and the set the break the normal way. Here's an example for Net::SSLeay::open_tcp_connection:

    DB<1> use Net::SSLeay DB<2> b Net::SSLeay::open_tcp_connection Subroutine Net::SSLeay::open_tcp_connection not found. DB<3> x Net::SSLeay::open_tcp_connection() 0 0 1 '-e 743: open_tcp_connection: destination host not found: `\' (port + ) () ' DB<4> b Net::SSLeay::open_tcp_connection DB<5>

    So, the second attempt to set the breakpoint works. You might want to consult the sub's documentation for the (unlikely) case that calling it has unwanted side effects.

    Edit: s/module/subroutine/
Re: using perldb
by GrandFather (Saint) on Sep 02, 2021 at 05:03 UTC

    What sub? Can you show us a short complete script that demonstrates the problem?

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond