AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Debug.pm view on Meta::CPAN
}
my $path = shift;
$path =~ s%^\./%%;
$path
}
=item AnyEvent::Debug::cb2str $cb
Using various gambits, tries to convert a callback (e.g. a code reference)
into a more useful string.
Very useful if you debug a program and have some callback, but you want to
know where in the program the callback is actually defined.
=cut
sub cb2str($) {
my $cb = shift;
"CODE" eq ref $cb
or return "$cb";
eval {
my $cv = B::svref_2object ($cb);
my $gv = $cv->GV
or return "$cb";
my $name = $gv->NAME;
return (AnyEvent::Debug::path2mod $gv->FILE) . ":" . $gv->LINE
if $name eq "__ANON__";
$gv->STASH->NAME . "::" . $name;
} || "$cb"
}
sub sv2str($) {
if (ref $_[0]) {
if (ref $_[0] eq "CODE") {
return "$_[0]=" . cb2str $_[0];
} else {
return "$_[0]";
}
} else {
for ("\'$_[0]\'") { # make copy
substr $_, $Carp::MaxArgLen, length, "'..."
if length > $Carp::MaxArgLen;
return $_;
}
}
}
=item AnyEvent::Debug::backtrace [$skip]
Creates a backtrace (actually an AnyEvent::Debug::Backtrace object
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";
( run in 0.567 second using v1.01-cache-2.11-cpan-39bf76dae61 )