簡體   English   中英

從Perl腳本創建/引發SIGINT(Ctrl-C)-並導致從模具處理程序進入調試器進入步驟模式?

[英]Create/raise a SIGINT (Ctrl-C) from Perl script - and cause debugger entry in step mode from die handler?

我正在嘗試調試Perl(在Linux下)中一個相當復雜的程序時遇到了問題。 我可以在這里使用簡單的代碼段( 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";

運行該程序將退出:

$ perl test.pl 
Array is now 10000 elements long
Can't use an undefined value as an ARRAY reference at test.pl line 22.

因此,現在我想對其進行調試-但該錯誤導致程序死亡,並退出調試器:

$ 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
$ 

然后,我在調試器(PerlMonks)中發現了警告中斷 所以我嘗試添加:

...
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 = ();
...

...但是這也會殺死調試器:

$ 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.  

現在,我知道如果我用Ctrl-C中斷程序-通常會導致調試器進入步進模式; 例如,您可以設置my $numelems = 100000000; ,並且在循環播放時,按Ctrl-C鍵-您可以調試:

$ 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

現在,我可以將斷點插入源perl程序中

...
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
  $DB::single = 1;               ### <=== BREAK HERE
  my @minientry = @{$testa[$ix]};
...

但是當$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

...而且我不想遍歷10000個元素來解決有問題的部分:)

因此,我認為以下內容-如果有一種方法可以從Perl腳本本身中引發/生成/創建SIGINT(Ctrl-C),那么我將能夠從die處理程序中引發它,並希望引起這一點。進程終止之前的調試器。 因此,我的問題是:

  • 是否有可能從Perl腳本中引發SIGINT,該腳本會自行中斷-如果是這樣,怎么辦?
  • 如果可以使用前一種方法,那么在過程結束之前,是否可以使用模具處理程序中的Ctrl-C進入調試器步進模式?
  • 如果以前是不可能的-什么可能性我必須引起進入調試器步模式,就在所在行的程序die S'

順其自然(盡管不確定我是否理解正確:) ),這要歸功於這些:

只需使用eval包裝修改代碼,並warn如下warn

...
# loop through array/list of arrays
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
  eval {
    my @minientry;
    @minientry = @{$testa[$ix]};
    $sum += $minientry[0];
  }; # just this causes step into debugger at $ix = 10001
  warn $@ if $@; # this causes step into debugger at $ix=10000 (OK)
}
...

...然后調試器的工作方式如下:

$ 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 27.

main::(test.pl:30):   warn $@ if $@; # this causes step into debugger at $ix=10000 (OK)
  DB<1> p $ix
10000
  DB<2> p @{$testa[$ix]}

  DB<3> p @{$testa[$ix-1]}
99991
  DB<4> p join("--", @{$testa[$ix]})

  DB<5> p join("--", @{$testa[$ix-1]})
9999--1
  DB<6> q

...就是直接進入有問題的行,這就是我想要的。

好吧,希望這對某人有幫助,
干杯!

編輯:也可能相關: 為什么在使用eval之前我需要本地化$ @?

可以將$DB::single設置為一個表達式,這樣它只會在您指定的條件下中斷。

...
for (my $ix = 0; $ix < $BADnumelems; $ix++) {

  $DB::single ||= ref($testa[$ix]) ne 'ARRAY';

  my @minientry = @{$testa[$ix]};
  $sum += $minientry[0];
}
...

...
for (my $ix = 0; $ix < $BADnumelems; $ix++) {
  eval {
      my @minientry = @{$testa[$ix]};
      $sum += $minientry[0];
  };
  $DB::single ||= $@; # break if eval block fails
  # give debugger somewhere to break before proceeding to next iteration
  1;
}
...

(我更喜歡$DB::single ||= ... $DB::single = ...因為如果您確實要逐步執行該塊中的每個迭代(或該塊之后的任何代碼),Perl將需要設置$DB::single為true,並且您不希望您的代碼無意中取消該值並阻止您單步執行其他代碼行。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM