develooper Front page | perl.perl5.porters | Postings from May 2013

Re: carp::longmess

Ben Tilly
May 3, 2013 06:26
Re: carp::longmess
Message ID:
I have no idea what recent changes there have been to Carp recently.
I lost interest in p5p after it became apparent to me that the time
frame from submitting a patch until I could rely on using it inside of
my daily life was longer than my average period of employment.  This
made the inevitable frustrations of what was required to get anything
useful done unbearable.

All that I can provide is perspective.  At the time that I worked on
things, the only CPAN module that I was aware of which cared about
longmess was CGI::Carp.  And I was aware of nobody anywhere using
$Carp::CarpLevel in non-buggy code (certainly the way it was used
inside of was horribly buggy, and Exporter had similar but
smaller bugs).  What the current situation is, I do not know.

Historically shortmess, longmess, and $Carp::CarpLevel were NOT
DOCUMENTED.  In Larry Wall's original version, for good reasons.
Because his was a hack with a lot of good ideas but very subtle
behavior that was easy to miss.  The complications of which became
apparent when other programmers tried to create a nice warnings
system, without actually understanding Carp, with the result that
warnings emitted usually were full stack backtraces and sometimes were
one line messages from near the top of the program (and nowhere near
the likely bug).  With the useless behavior being more likely to
happen in complex code bases.

When I got annoyed enough at unreliable error messages from warnings
to rewrite Carp in a way that would make it possible to solve those, I
also chose to NOT DOCUMENT THEM because it was apparent that
attempting to use them was for most programmers - even good
programmers - an invitation to wrong code.  And I was not confident
that my version wouldn't get rewritten by someone else, so I didn't
publicly document my new internals because I didn't want to force a
future implementer to stick with my approach.  (I was sensitive to
this because I was trying to rewrite it and was forced to make old
internals work properly.)  However for backwards compatibility, I made
the old internals work as they had because CGI::Carp (at the time a
CPAN module) relied on it.  That was where I ran out of tuits,.  I
matched the internal behavior, but never added all of the unit tests
that I should have.  I did fix Exporter, but not warnings, which was
the main point of this work.  (The issue is that when warnings was
created it was noticed that errors sometimes came from nowhere
sensible, the reason was not tracked down, and someone threw up unit
tests for bad behavior "just in case" anyone ever relied on it.  That
battle is what did me in, I didn't want to face arguments about, "You
can't change this behavior that is undocumented and constantly messing
people up, we don't know who is relying on it!"  To whoever eventually
completed that project - thank you.)

Someone else later decided to document those internal interfaces under
the theory that they might be useful to someone, AND GOT THEM WRONG.
(The mistakes made were exactly the ones that had lead to the
unreliable error messages that caused me to rewrite Carp in the first
place...)  Because they had now been documented publicly, the decision
was made that they couldn't be undocumented.  When this was raised to
my attention I documented them, then left again.  I seem to have
failed to document the fact that when you call longmess, you get one
less call frame than you do if you call cluck.  Sorry.  If it had been
my choice, longmess would not even have been mentioned because its
behavior difference makes no sense unless you know the history...

If someone else has the energy to wade into this morass, good luck.  I
entered with great dreams about making error reporting both more
reliable and simpler to use.  I put in a lot of work, solved a small
Exporter bug, and created a flexible mechanism for controlling the
reporting of errors that I'm not sure has been used by anyone other
than myself.

On Wed, May 1, 2013 at 6:16 AM, Uri Guttman <> wrote:
> hi ben,
> your name came up on p5p with regard to carp::longmess. seems you commented
> on a backwards compatibilty issue and the whole problem surfaced. you
> haven't been on p5p in a while so i said i would contact you to let you
> know. maybe you can jump in again and help. here is rjbs's recent post
> mentioning you.
> thanx,
> uri
> * "Michael G. Schwern" <> [2013-04-23T11:00:07]
>> I would like to see the warning and top level mistake fixed.  That is a
>> clear regression.  The rest can wait.
>> $ perl -wle 'use Carp;  print Carp::longmess("Foo")'
>> Foo at -e line 1.
>> $ perlbrew use perl-5.17.10
>> $ perl -wle 'use Carp;  print Carp::longmess("Foo")'
>> Use of uninitialized value in concatenation (.) or string at
>> […]
>> Let me poke at it again now.
> Any luck? :)
> I did some poking and talking, too.  You mention the "icky compatibility
> wrapper," which does this:
>     local $CarpLevel = $CarpLevel + 1;
> ...for non-Internal callers.  Frustratingly, there are no tests for this
> behavior.  If we remove that line, all the tests pass *and* your oneliner
> does
> the right thing again.  The "the story is" comment was introduced by:
>   commit d735c2efe0b08b05adfb893625476bf4480a2ece
>   Author: Ben Tilly <>
>   Date:   Sun Oct 22 07:07:23 2006 -0700
>     Re: Why aren't %Carp::Internal and %Carp::CarpInternal documented?
>     From: "Ben Tilly" <>
>     Message-ID: <>
> That message is:
> The actual CarpLevel+1 seems to come from:
>   commit c01c1f0dc3aef0fc53c73558fd9554442d6c8540
>   Author: Ben Tilly <>
>   Date:   Sun Dec 2 06:32:51 2001 -0500
>     RE: More verbose POD for Carp
>     Message-ID: <>
>     p4raw-id: //depot/perl@13426
> That message is:
> There, the intent is clear: a goto is being replaced by a subroutine call,
> so
> one more frame has to be accounted for.  I believe that the changes to
> long_error_loc have made this redundant.  I have only gazed adoringly at
> this
> code, though, not carefully traced it.  I don't know when this may have
> happened, as removing that line before doy's work still causes no breakage.
> I
> need to get to bed so I can't bisect right now.
> That said... here is the code as it stands:
>    1      sub longmess {
>    2          # Icky backwards compatibility wrapper. :-(
>    3          #
>    4          # The story is that the original implementation hard-coded the
>    5          # number of call levels to go back, so calls to longmess were
> off
>    6          # by one.  Other code began calling longmess and expecting
> this
>    7          # behaviour, so the replacement has to emulate that behaviour.
>    8          my $cgc = _cgc();
>    9          my $call_pack = $cgc ? $cgc->() : caller();
>   10          if ( $Internal{$call_pack} or $CarpInternal{$call_pack} ) {
>   11              return longmess_heavy(@_);
>   12          }
>   13          else {
>   14              local $CarpLevel = $CarpLevel + 1;
>   15              return longmess_heavy(@_);
>   16          }
>   17      }
> Removing line 14 seems to solve our woes, possibly breaking things
> un-tested-for.  Replacing lines 10-16 with line 11 also leaves everything
> passing, of course.  Woe befall he who deletes line 9, though.  Tests rely
> on that callback getting called, even if you don't use it.
> Fine.
> Anyway, the bare minimum of what we need is:
> 1) a test for the problem Schwern has reported, suitable for adding to the
> dist
> 2) some further eyes investigating whether removing line 14 above is
> actually
>    okay; I'm not sure Ben Tilly is around anymore; last p5p post, 2009?
> -- rjbs
> Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About