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

Hi, friends. So we use "croak" all the time. We have some code though that does some dynamic dispatching, and the "croak" shortmess (only showing the caller origin) is inadequate. All we see is the error happening in the "dispatch" routine, but we really need to see where it was dispatched *to*. Of course, just using "die" in this situation work fine; it shows the actual location of the croak. But we since we use "croak" so often, we screw it up sometimes and use croak rather than die. So my question is: is there a way to coax Carp::croak into showing *both* the caller and the callee of the croak call? Another alternative is to use $Carp::Verbose, so we get a full backtrace -- that does indeed work too. Just that it also generates a huge callstack that we'd rather not see on every exception. If Carp::croak cannot be convinced to do this, any suggestions? Maybe write our own "croak" routine that uses Carp's shortmess()?
  • Comment on Getting croak to show both caller and callee?

Replies are listed 'Best First'.
Re: Getting croak to show both caller and callee?
by Laurent_R (Canon) on Apr 25, 2015 at 08:47 UTC
    This may seem obvious and also may not be what you are looking for, but, just in case, what about using Carp::confess in those cases where you want more information, and Carp::croak when you don't need the full information. At least, this is a bit more fine tuned that setting $Carp::Verbose to true.

    Je suis Charlie.

      You can also make croak give a stack trace from the command line.

      export PERL5OPT=-MCarp::Always script
      or
      perl -MCarp::Always script script
Re: Getting croak to show both caller and callee?
by Don Coyote (Hermit) on Apr 25, 2015 at 07:12 UTC

    The callee is dynamically generated, but the code croaks before the callee is generated, or after? Deterministic dynamicity would suggest you could pass an extra variable in the callers arguments which would be passed to croak for debugging. Dynamicity being non-deterministic, there would not be any scope for Croak to be making predictions about where your code may end up.

    Evaluating the dynamic code would allow you to see where the evaluation was dying returning $@ messages back through Croak when evaluation fails. Or using warn instead of die to allow the code to continue to evaluate and hence allowing you to determine where it is ending up, instead of where it should.

    You may already be aware of these strategies, so without a little more detail, as Anonymous Monk priorly suggested...

Re: Getting croak to show both caller and callee?
by Anonymous Monk on Apr 25, 2015 at 19:33 UTC

    Thanks for the replies.

    And just to clarify, I *can* get what I need by correctly using croak/die/confess/warn in the appropriate places or by adding additional details to the actual exception message. This is more a question of DWIW when we mistakenly use croak() in a spot where die() would been more informative.

    Here's some example code. And yes, it's completely insecure; it's just to demonstrate the issue.

    #!/usr/bin/env perl { package MyModule; use strict; use warnings; use Carp; sub a { croak 'croaking' } sub b { die 'dying' } sub dispatch { my $class = shift; my $method = shift or croak 'no method name supplied'; $class->$method; } } while (<>) { chomp; next unless /\S/; eval { MyModule->dispatch($_) }; warn $@ if $@; }

    If you run it and enter 'b', you'll see: "dying at ./try line 11, <> line 2." Line 11 is in fact the b() routine, so that's great.

    Now enter 'a' and you get: "croaking at ./try line 25." That is not helpful, since line 25 is just the dispatch routine. We have no idea what was dispatched that raised the error.

    So ideally, what I would like to see is the first two call frames of the stack, rather than only the second.

    IOW, croak() would emit something like this by default:

    croaking at ./try line 12, <> line 1.
    	MyModule::a("MyModule") called at ./try line 19
    

    Any thoughts on how to accomplish that?

    Thanks!

      Any thoughts on how to accomplish that?

      Here’s one: Change use Carp; to use MyCarp; and put the module “MyCarp.pm” somewhere in your Perl’s path:

      #! perl package MyCarp; use strict; use warnings; use Exporter 'import'; our @EXPORT = 'croak'; sub croak { use Carp 'shortmess'; $Carp::Verbose = 1; my @lines = split /\n/, shortmess @_; s/^\s+// for @lines; die $lines[1] . "\n\t" . $lines[2] . "\n"; } 1;

      Example output:

      17:22 >perl 1229_SoPW.pl b dying at 1229_SoPW.pl line 23, <> line 1. a MyCarp::croak("croaking") called at 1229_SoPW.pl line 22 MyModule::a("MyModule") called at 1229_SoPW.pl line 30 b dying at 1229_SoPW.pl line 23, <> line 3. Terminating on signal SIGINT(2) 17:22 >

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

        Beautiful, Athanasius. Thank you!
Re: Getting croak to show both caller and callee?
by Anonymous Monk on Apr 25, 2015 at 05:26 UTC

    Hmmm. Sorry, formatting sucked. Here it is again.

    Hi, friends.

    So we use "croak" all the time. We have some code though that does dynamic dispatching, and the "croak" shortmess (only showing the caller origin) is inadequate. All we see is the error happening in the "dispatch" routine, but we really need to see where it was dispatched *to*.

    Of course, just using "die" in this situation works fine; it shows the actual location of the croak. But since we use "croak" so often, we screw it up sometimes and use croak rather than die.

    So my question is: is there a way to coax Carp::croak into showing *both* the caller and the callee of the croak call?

    Another alternative is to use $Carp::Verbose, so we get a full backtrace -- that does indeed work too. Just that it also generates a huge callstack that we'd rather not see on every exception.

    If Carp::croak cannot be convinced to do this, any suggestions? Maybe write our own "croak" routine that uses Carp's shortmess()?

Re: Getting croak to show both caller and callee?
by Anonymous Monk on Apr 25, 2015 at 06:23 UTC

    Croak despatches messages to callees STDOUT and STDERR, in my understanding. Can you expand on these terms and maybe provide a short code example to clarify your definitions/requirements please.