magical goto in __WARN__ handler

P

Peter Michael

Hi,

is the use of magical "goto" deprecated in __WARN__ and
__DIE__ handlers?

Consider the following simple attempt to provide stack traces for all
warnings:

use Carp ();
local $SIG{__WARN__} = sub
{ unshift @_, "[stack trace by warn handler] ";
goto &Carp::cluck;
};

When calling warn() this results in an endless loop.

The "goto" is intended to hide the calling of the handler in order not
to appear in the stack trace produced by cluck(). Carp::cluck() uses
warn() itself to generate the message, but the handler is disabled during
its call.

perlfunc says about goto: "Instead, it exits the current subroutine
(losing any changes set by local()) and immediately calls in its place
the named subroutine using the current value of @_."

From the wording "calls in its place" I infer that Carp::cluck becomes
$SIG{__WARN__} at this point having the same effect as

local $SIG{__WARN__} = \&Carp::cluck;

except for manipulating @_ before.

However "goto" seems to revert the effect of disabling the handler
during its call. Why (and how) is this done?

I am grateful for any explanations and hints.

Regards,

Peter
 
A

Anno Siegel

Peter Michael said:
Hi,

is the use of magical "goto" deprecated in __WARN__ and
__DIE__ handlers?

Consider the following simple attempt to provide stack traces for all
warnings:

use Carp ();
local $SIG{__WARN__} = sub
{ unshift @_, "[stack trace by warn handler] ";
goto &Carp::cluck;
};

When calling warn() this results in an endless loop.

The "goto" is intended to hide the calling of the handler in order not
to appear in the stack trace produced by cluck(). Carp::cluck() uses
warn() itself to generate the message, but the handler is disabled during
its call.

perlfunc says about goto: "Instead, it exits the current subroutine
(losing any changes set by local()) and immediately calls in its place
the named subroutine using the current value of @_."

I'm not too surprised by that behavior. It seems the flag that
disables the handler follows "local" semantics and is reset on
"goto &...".

As a workaround you could call Carp::longmess (in a normal call)
and clean up the unwanted stack frame.

Anno
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,160
Messages
2,570,890
Members
47,423
Latest member
henerygril

Latest Threads

Top