I'm having a problem with a rather complex program in Perl (under Linux), which I'm trying to debug. I can simulate the problem with the simple snippet here (test.pl
):
use warnings;
use strict;
use feature qw/say/;
my @testa = ();
my $numelems = 10000;
# populate array/list of arrays
for (my $ix = 0; $ix < $numelems; $ix++) {
my @miniarr = ($ix, 1);
push(@testa, \@miniarr);
}
say "Array is now " . scalar(@testa) . " elements long";
my $BADnumelems = $numelems + 2;
my $sum = 0;
# loop through array/list of arrays
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
my @minientry = @{$testa[$ix]};
$sum += $minientry[0];
}
say "Sum of elements is $sum";
Running this program exits with:
$ perl test.pl
Array is now 10000 elements long
Can't use an undefined value as an ARRAY reference at test.pl line 22.
So, now I'd like to debug it - but the error causes the program to die, and exit the debugger:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): my @testa = ();
DB<1> c
Array is now 10000 elements long
Can't use an undefined value as an ARRAY reference at test.pl line 22.
at test.pl line 22
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
DB<1> p $sum
DB<2> exit
$
Then, I found break on warning in debugger (PerlMonks); so I tried adding this:
...
use feature qw/say/;
$SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
$SIG{__WARN__} = sub { my($signal) = @_; say "WARNhandler: $signal"; $DB::single = 1; };
my @testa = ();
...
... but this also kills the debugger:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): $SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
DB<1> c
Array is now 10000 elements long
DIEhandler: Can't use an undefined value as an ARRAY reference at test.pl line 25.
Can't use an undefined value as an ARRAY reference at test.pl line 25.
Debugged program terminated. Use q to quit or R to restart,
use o inhibit_exit to avoid stopping after program termination,
h q, h R or h o to get additional info.
Now, the thing is, I know that if I interrupt the program with Ctrl-C - that usually causes the debugger to enter into step mode; for instance, you can set my $numelems = 100000000;
, and while it's looping, press Ctrl-C - and you can debug:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): $SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
DB<1> c
^Cmain::(test.pl:14): my @miniarr = ($ix, 1);
DB<1> p $ix
148607
DB<2> q
Now, I can insert break point into source perl program:
...
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
$DB::single = 1; ### <=== BREAK HERE
my @minientry = @{$testa[$ix]};
...
but it enters the loop when $ix = 0
:
$ perl -d test.pl
Loading DB routines from perl5db.pl version 1.32
Editor support available.
Enter h or `h h' for help, or `man perldebug' for more help.
main::(test.pl:6): $SIG{__DIE__} = sub { my($signal) = @_; say "DIEhandler: $signal"; $DB::single = 1; };
DB<1> c
Array is now 10000 elements long
main::(test.pl:26): my @minientry = @{$testa[$ix]};
DB<1> p $ix
0
DB<2> q
... and I don't want to step through 10000 elements to get to the problematic part :)
So, I thought the following - if there is a way to raise/generate/create SIGINT (Ctrl-C) from the Perl script itself, then I'd be able to raise it from the die handler, and hopefully cause a step in the debugger before the process dies. So, my questions are:
- Is it possible to raise SIGINT from a Perl script, which will break itself - if so, how?
- If the previous is possible, would it be able to cause entry into debugger step mode using Ctrl-C from a die handler, before the process dies?
- If the previous is not possible - what possibility do I have to cause an entry into debugger step mode, right at the line where program
die
s?