Home > OS >  Can I enable a `$DB::single =1` breakpoint conditionally from a program?
Can I enable a `$DB::single =1` breakpoint conditionally from a program?

Time:05-28

I have a case where a local variable in a sub has the wrong un-blessed value after several invocations, and I'd like to break to the Perl debugger (when the program runs under debugger control, of course) if a specific condition is met.

I could try a conditional breakpoint interactively, but that would be a lot of typing work when repeating the "modify, debug" cycle many times.

Anyway I'd like to know whether its possible to use a construct like $DB::single=1 if (...);. When I tried it, it did not work, and the breakpoint was active all the time.

So is it possible?

What I had tried

Basically my problem is that the line @l_socks = @{$lsa->sockets()}; triggered a "Can't call "sockets" on unblessed reference at ...". As the code is in a subroutine that is called many times before the problem happens, I added $DB::single = 1 unless (ref $lsa); before the problematic line, but that did not work.

So maybe my problem is that $lsa is not a scalar as expected, but a reference; unblesswd however.

CodePudding user response:

Yes, you can do that. It breaks at the next breakable line.

Consider the following program.

use strict;
use warnings;

print "hello";

for my $foo ( 1.. 10 ) {
    print "$foo\n";
    if ($foo == 9) {
        $DB::single = 1;
    }
}

There's a conditional breakpoint when $foo is 9. The breakpoint gets set after the print. It turns the breaks on, but it only stops at the next breakable line, which is the print line for when $foo is 10.

$ perl -d breaking.pl

Loading DB routines from perl5db.pl version 1.51
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(breaking.pl:4):  print "hello";
  DB<1> r
hello1
2
3
4
5
6
7
8
9
main::(breaking.pl:7):      print "$foo\n";
  DB<1> l
7==>        print "$foo\n";
8:      if ($foo == 9) {
9:          $DB::single = 1;
10      }
11  }
12  
  DB<1> x $foo
0  10
  DB<2> r
10
Debugged program terminated.  Use q to quit or R to restart,

So you need to do your check at the top of whatever it is you want to inspect.

CodePudding user response:

For completeness, here is the "answer" to my question:

$DB::single = 1 correctly enables a debugger breakpoint after the instruction following the command if the condition to trigger it is correct.

In my case I used an incorrect condition that would never trigger, so it seemed the $DB::single = 1 was ignored.

Fixing the condition fixed the problem. For the code example shown (you are not expected to understand the details; SocketArray is a package written for this program), using

unless (UNIVERSAL::isa($lsa, 'SocketArray') {
    $DB::single = 1;
    1;
}

fixed it, and the debugger stopped at 1; when it triggered.

  • Related