Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Finding what called a subroutine

by Anonymous Monk
on Apr 05, 2013 at 23:27 UTC ( [id://1027229]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have an error happening, but I cannot find with any debugging it... whatever is happening is calling a subroutine, so how can I print out the line and file that *called* the subroutine that is executed?

The subroutine is in a file that is in one of the many files, so I don't know which file is generating the error, so I need to track the subroutine and what called it. I have the debugging reporting to me, before it exits out, but I don't know how to check what called it and what file it was in, if possible.

is it even possible?

Thanks,
Richard

Replies are listed 'Best First'.
Re: Finding what called a subroutine
by davido (Cardinal) on Apr 05, 2013 at 23:46 UTC

    See Carp:

    use Carp qw(croak); sub foo { croak; } foo();

    Here, carp reports from the perspective of the caller. In this case, it will report both the line in the sub that died, and the line in the calling code that called the sub that died.

    If you run the code above as "mytest.pl", unmodified it would output the following:

    at ./mytest.pl line 4. main::foo() called at ./mytest.pl line 7

    The Carp module also provides "confess" which will offer a more detailed back-trace.

    If you just want to log calls you can use Carp's "carp" and "cluck" functions to get similar output to warn, but from the caller's perspective.


    Dave

Re: Finding what called a subroutine
by educated_foo (Vicar) on Apr 06, 2013 at 08:20 UTC
    Yes, you can use caller:
    ($pkg, $file, $line) = caller(1);
    Or see Carp's croak() and confess().
      Very much recommend caller(), as educated_foo says; you can get a full stack trace all the way back to the main program if you need it.
Re: Finding what called a subroutine
by clueless newbie (Curate) on Apr 06, 2013 at 16:01 UTC

    Assuming that one has access to the commandline one could always use Carp::Always or Devel::SimpleTrace via perl's -M option or perl's PERL5OPT.

    If one is interested in the arguments being passed insert an INIT block of the form

    INIT { require Data::Dumper; require Scalar::Util; # And now redefine Carp::format_arg so Carp can dump refs too! no warnings qw(once redefine uninitialized); *Carp::format_arg=sub { my $arg_S=shift; my $return_s; if (not defined $arg_S) { # It's an undef $return_s='undef'; } elsif (Scalar::Util::blessed($arg_S)) { # It's an object my $buffer_s; { local $Data::Dumper::Indent=0; local $Data::Dumper::Terse=0; # deparse any CodeRefs local $Data::Dumper::Deparse=ref($arg_S) eq 'CODE'; $buffer_s=Data::Dumper::Dumper($arg_S); $buffer_s=~ s/^\$VAR\d+\s*=\s*//; $buffer_s=~ s/;\s*$//; }; $return_s=$buffer_s; } elsif (ref($arg_S)) { # It's a ref Array, Code or Hash my $buffer_s; { local $Data::Dumper::Indent=1; #local $Data::Dumper::Terse=0; # deparse any CodeRefs local $Data::Dumper::Deparse=ref($arg_S) eq 'CODE'; $buffer_s=Data::Dumper::Dumper($arg_S); $buffer_s=~ s/^\$VAR\d+\s*=\s*//; $buffer_s=~ s/;\s*$//; $buffer_s=~ s/ */ /g if (ref($arg_S) eq 'CODE'); }; $return_s=$buffer_s; } else { $return_s=$arg_S; $return_s=~ s/'/\\'/g; $return_s=Carp::str_len_trim($arg_S,$Carp::Heavy::MaxArgLe +n); $return_s="'$arg_S'" unless $arg_S =~ /^-?[\d.]+\z/; } $return_s=~ s/([[:cntrl:]]|[[:^ascii:]])/sprintf("\\x{%x}",ord +($1))/eg; return $return_s; }; # Carp::format_arg; }

    into Carp::Always.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1027229]
Approved by tobyink
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (2)
As of 2024-04-19 01:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found