[% setvar title Change the way $SIG{__WARN__} and $SIG{__DIE__} are used %]

This file is part of the Perl 6 Archive

Note: these documents may be out of date. Do not use as reference!

To see what is currently happening visit http://www.perl6.org/

TITLE

Change the way $SIG{__WARN__} and $SIG{__DIE__} are used

VERSION

  Maintainer: Chris Hostetter <chrish@cnet.com>
  Date: 15 Sep 2000
  Mailing List: perl6-language@perl.org
  Number: 236
  Version: 1
  Status: Developing

ABSTRACT

The current method in which __WARN__ and __DIE__ signal handlers are used is limited in 2ways:

DESCRIPTION

Parameter Treatment

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";

Nested Handlers

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.

IMPLEMENTATION

Unknown.

REFERENCES

Programming Perl, 2nd Ed -- p139

Programming Perl, 2nd Ed -- p157

Programming Perl, 2nd Ed -- p241