Subject: | Ebug's feature to interrupt w/SIGINT doesn't work (returns to console) |
The following sequence as input into pcalc.pl (attached):
causes pcalc to infinitely loop:
sub logb ($$) { state @logs; return log($_[1]) / ($logs[$_[0]] ||= log
$_[0]) }
sub ss($){2**(int logb(2,$_[0])-2)}
ss(256*1024)
<hangs> -- so I input 2 functions, then call the 2nd...and 'byebye'
Trying to debug 'why'... trying to interrupt pcalc using
sigint -- bug instead of getting to the debugger,
it exits to console.
When I have the ExceptionHandler enabled, and press
control-\, (SIGTERM), I at least get a traceback from
my handler, but it comes from random places inside Math
BIG(int/float/whatever)....so it's not clear what is going on.
I disabled ExceptionHandler, thinking it might be getting in the way.
Nada...
(sigh)....
I'll include ExceptionHandler in case you want to see a traceback ...
in the code, just uncomment the "use ExceptionHandler"
and Register_Traceback; & Register_Traceback('QUIT'); lines
(probably don't want to uncomment the one for INT if you are
trying to catch that in ebug! ;-)
Rest should be available on CPAN...
Subject: | pcalc.pl |
Message body is not shown because it is too large.
Subject: | ExceptionHandler.pm |
#!/usr/bin/perl -w
{
package ExceptionHandler;
use warnings; use 5.14.0;
use P;
use Dbg;
our @ISA=qw(Exporter);
our @EXPORT=qw ($_Warn_Count $_Die_Warn_Count
Register_Traceback Cancel_Tracebacks Cancel_Traceback);
use Carp qw(confess cluck);
use Readonly; sub RO(\[$@%]@){goto &Readonly};
RO my $ShowTraceback => 0x10;
RO my $HaveHander => 0x20;
our %Internals=(ExceptionHandler=>1, ErrHandler=>1, Dbg=>1, Mem=>1,
'Data::Vars'=>1, Data=>1);
our $_Die_Warn_Count=-1;
our $_Warn_Count=0;
our %exceptions;
sub Cancel_Tracebacks() { $SIG{$_} = 'DEFAULT' for keys %exceptions }
sub Cancel_Traceback () {goto &Cancel_Tracebacks}
sub generic_handler($;$$) { # no countdown handles cases -1,0,8,16
my $sigaction=shift; #nxt parm might be handler for 0x20 case
my ($sig, $handler) = @_;
if ($sigaction < 0) {
Cancel_Tracebacks;
exit(0);
}
if ($sigaction & 0x10 || $sigaction == 0) {
cluck @_;
}
if ($sigaction & 0x20) {
$SIG{$sig} = $handler;
return;
}
Cancel_Tracebacks;
exit(0);
}
# sig, callback|disposition
# disposition = sign-bit=exit immediate
# = (0)= exit
# = 1-7 if (devel){stack trace} + ignore X times + exit
# = 0x10 = message/nomessage
# = 0x20 = 0=count in bottom nibble, 1=noexit
# = callback and status returns above val for further processing
sub _register_handler($;$) {
my ($sig, $action) = @_;
$exceptions{$sig}=1;
$action=0x10 unless defined $action;
if (ref $action) {
my $sigaction=$action;my $thissig=$sig;
#call user handler 1st, its' exit val passed to generic handler
my $handler;
$handler=$SIG{$sig}=
sub { generic_handler($sigaction->(@_), $thissig, $handler)};
} elsif ($action<0 || $action==0 || $action & 0x20 ) {
my $sigaction=$action;
my $handler;
$handler=$SIG{$sig}=sub { generic_handler($sigaction, $handler)};
} else {#counter's go here...
my $sigaction=$action;
my $handler=$SIG{$sig}=
sub {
cluck @_ if $action & 0x10;
if ($sigaction&0xf) {
--$sigaction;
return if $sigaction&0xf;
}
Cancel_Tracebacks;
exit(2);
};
}
}
sub Register_Traceback (;$$) {
my ($sig, $action) = @_;
$Carp::Internal{$_}=$Carp::CarpInternal{$_} = 1 for keys %Internals;
if (@_ && $_[0] =~ m{^allow[-_]?warnings[^\d]*(\d+).*$}i) {
$1 and $_Die_Warn_Count=$1;
shift;
}
unless (@_) { #default is to setup die+warn handlers
$exceptions{__DIE__}=1;
$SIG{__DIE__} = sub {
$SIG{__DIE__}='DEFAULT';
if (defined $^S) { confess @_ } else { print STDERR @_ }
exit -1;
};
$exceptions{__WARN__}=1;
$SIG{__WARN__} = sub {
if (defined $^S) { cluck @_; } else { print STDERR @_ }
if ($_Die_Warn_Count && --$_Die_Warn_Count<=0) {
$SIG{__DIE__} = 'DEFAULT';
exit (2)
}
};
} else {
if (ref $sig eq 'ARRAY') {
my @args=@_; my $sigs=$_[0];
_register_handler(@args) foreach $args[0] (@$sigs);
} else {
_register_handler($_[0], @_[1..$#_]);
}
}
}
use Exporter;
1;}