[% setvar title Change the way $SIG{__WARN__} and $SIG{__DIE__} are used %]
To see what is currently happening visit http://www.perl6.org/
Change the way $SIG{__WARN__} and $SIG{__DIE__} are used
Maintainer: Chris Hostetter <chrish@cnet.com> Date: 15 Sep 2000 Mailing List: perl6-language@perl.org Number: 236 Version: 1 Status: Developing
The current method in which __WARN__ and __DIE__ signal handlers are
used is limited in 2ways:
The current behavior of warn and die is to first concatenate the
parameter LIST into a single string, before checking if there is a
user specified signal handler. Then pass that string as a single
argument to any handler if it exists.
I propose, that a registered signal handler for __WARN__ or __DIE__
should be passed the exact same LIST of arguments that the
corresponding warn or die call received. This would allow complex
programs to use the warn/die signal handling mechanism to for dealing
with complex exception handling, and still recognize low level
warnings / errors from the interpreter.
For example: It is reasonable when developing a large system to want a mechanism for dealing with "error levels" -- one such approach would be something like the following...
# use this function EXCLUSIVELY in your code for dealing with
# warnings or errors so that the appropraite acction is taken
sub errorHandle {
my $level = shift;
my @msgs = @_;
if ($config{abort_level} < $level) {
die "Fatal Error ($level): ", @msgs;
}
if ($config{warn_level} < $level) {
warn "Warning ($level): ", @msgs;
}
if ($config{log_level} < $level) {
# log something about @msgs
}
# etc ...
}
# want to make sure we catch things from interpreter and
# code from CPAN
$SIG{__WARN__} = sub { &errorHandler(9, @_); }
$SIG{__DIE__} = sub { &errorHandler(11, @_); }
# ...
&validateSomething($someArg) or errorHandle 9, "couldn't validate";
The problem with this, is that it requires you to use the non standard "errorHandle" function explicitly in your code. If you are writing a module that you plan on distributing to others, this is not ideal.
This would be far better, but would require that $SIG{__WARN__}
(and $SIG{__DIE__}) received the same list of parameters that warn (and
die) received...
# want to make sure we catch things from our code, the
# interpreter, or code from CPAN
$SIG{__WARN__} = sub {
my $level = $config{default_warn_level};
(1 < scalar(@_)) ? $level = shift;
my @msgs = @_;
if ($config{abort_level} < $level) {
die "Fatal Error ($level): ", @msgs;
}
if ($config{warn_level} < $level) {
warn "Warning ($level): ", @msgs;
}
if ($config{log_level} < $level) {
# log something about @msgs
}
# etc ...
}
$SIG{__DIE__} = sub { warn $config{default_warn_level}, @_; }
# ...
&validateSomething($someArg) or warn 9, "couldn't validate";
Currently, if a handler is called to deal with $SIG{__WARN__} or
$SIG{__DIE__} then the handler is disabled to prevent infinite
recursion if the handler itself calls die or warn.
It seems only logical, that if the current handler has been localized,
and overshadows an outer handler, then calling warn or die should
invoke the outer handler -- not the real warn or die. For example...
#!/usr/local/bin/perl -w
$SIG{__WARN__} = sub { print "outer handler: ", @_; };
sub bar {
warn "in bar";
}
sub foo {
local $SIG{__WARN__} = sub { warn "foo: ", @_; };
&bar();
}
&foo();
... this script causes "foo: in bar at warn.test.pl line 6." to be
written to standard error. I propose that "outer handler: foo: in bar
at warn.test.pl line 6." is more logical output.
This would allow modules to do their own __WARN__ and __DIE__ handling,
but still propagate the messages out to an application specific
handler.
Unknown.
Programming Perl, 2nd Ed -- p139
Programming Perl, 2nd Ed -- p157
Programming Perl, 2nd Ed -- p241