AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Debug.pm view on Meta::CPAN
that you can stringify), not unlike the Carp module would. Unlike the
Carp module it resolves some references (such as callbacks) to more
user-friendly strings, has a more succinct output format and most
importantly: doesn't leak memory like hell.
The reason it creates an object is to save time, as formatting can be
done at a later time. Still, creating a backtrace is a relatively slow
operation.
=cut
sub backtrace(;$) {
my $w = shift;
my (@bt, @c);
my ($modlen, $sub);
for (;;) {
# 0 1 2 3 4 5 6 7 8 9 10
# ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask, $hinthash)
package DB;
@c = caller $w++
or last;
package AnyEvent::Debug; # no block for speed reasons
if ($c[7]) {
$sub = "require $c[6]";
} elsif (defined $c[6]) {
$sub = "eval \"\"";
} else {
$sub = ($c[4] ? "" : "&") . $c[3];
$sub .= "("
. (join ",",
map sv2str $DB::args[$_],
0 .. (@DB::args < $Carp::MaxArgNums ? @DB::args : $Carp::MaxArgNums) - 1)
. ")"
if $c[4];
}
push @bt, [\($STRCACHE{$c[1]} ||= $c[1]), $c[2], $sub];
}
@DB::args = ();
bless \@bt, "AnyEvent::Debug::Backtrace"
}
=back
=cut
package AnyEvent::Debug::Wrap;
use AnyEvent (); BEGIN { AnyEvent::common_sense }
use Scalar::Util ();
use Carp ();
sub _reset {
for my $name (qw(io timer signal child idle)) {
my $super = "SUPER::$name";
*$name = sub {
my ($self, %arg) = @_;
my $w;
my $t = $TRACE;
my ($pkg, $file, $line, $sub);
$w = 0;
do {
($pkg, $file, $line) = caller $w++;
} while $pkg =~ /^(?:AE|AnyEvent::(?:Socket|Handle|Util|Debug|Strict|Base|CondVar|CondVar::Base|Impl::.*)|Coro::AnyEvent::CondVar)$/;
$sub = (caller $w)[3];
my $cb = $arg{cb};
$arg{cb} = sub {
++$w->{called};
local $TRACE_CUR = $w;
$TRACE_LOGGER->("enter $w") if $TRACE_ENABLED && $t;
eval {
local $SIG{__DIE__} = sub {
die $_[0] . AnyEvent::Debug::backtrace
if defined $^S;
};
&$cb;
};
if ($@) {
my $err = "$@";
push @{ $w->{error} }, [AE::now, $err]
if @{ $w->{error} } < 10;
AE::log die => "($w) $err"
or warn "($w) $err";
}
$TRACE_LOGGER->("leave $w") if $TRACE_ENABLED && $t;
};
$self = bless {
type => $name,
w => $self->$super (%arg),
rfile => \($STRCACHE{$file} ||= $file),
line => $line,
sub => $sub,
cur => "$TRACE_CUR",
now => AE::now,
arg => \%arg,
cb => $cb,
called => 0,
rt => \$t,
}, "AnyEvent::Debug::Wrapped";
delete $arg{cb};
$self->{bt} = AnyEvent::Debug::backtrace 1
if $WRAP_LEVEL >= 2;
( run in 0.662 second using v1.01-cache-2.11-cpan-0bb4e1dffa6 )