<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">package sigtrap;

=head1 NAME

sigtrap - Perl pragma to enable simple signal handling

=cut

use Carp;

$VERSION = 1.02;
$Verbose ||= 0;

sub import {
    my $pkg = shift;
    my $handler = \&amp;handler_traceback;
    my $saw_sig = 0;
    my $untrapped = 0;
    local $_;

  Arg_loop:
    while (@_) {
	$_ = shift;
	if (/^[A-Z][A-Z0-9]*$/) {
	    $saw_sig++;
	    unless ($untrapped and $SIG{$_} and $SIG{$_} ne 'DEFAULT') {
		print "Installing handler $handler for $_\n" if $Verbose;
		$SIG{$_} = $handler;
	    }
	}
	elsif ($_ eq 'normal-signals') {
	    unshift @_, grep(exists $SIG{$_}, qw(HUP INT PIPE TERM));
	}
	elsif ($_ eq 'error-signals') {
	    unshift @_, grep(exists $SIG{$_},
			     qw(ABRT BUS EMT FPE ILL QUIT SEGV SYS TRAP));
	}
	elsif ($_ eq 'old-interface-signals') {
	    unshift @_,
	    grep(exists $SIG{$_},
		 qw(ABRT BUS EMT FPE ILL PIPE QUIT SEGV SYS TERM TRAP));
	}
    	elsif ($_ eq 'stack-trace') {
	    $handler = \&amp;handler_traceback;
	}
	elsif ($_ eq 'die') {
	    $handler = \&amp;handler_die;
	}
	elsif ($_ eq 'handler') {
	    @_ or croak "No argument specified after 'handler'";
	    $handler = shift;
	    unless (ref $handler or $handler eq 'IGNORE'
			or $handler eq 'DEFAULT') {
    	    	require Symbol;
		$handler = Symbol::qualify($handler, (caller)[0]);
	    }
	}
	elsif ($_ eq 'untrapped') {
	    $untrapped = 1;
	}
	elsif ($_ eq 'any') {
	    $untrapped = 0;
	}
	elsif ($_ =~ /^\d/) {
	    $VERSION &gt;= $_ or croak "sigtrap.pm version $_ required,"
		    	    	    	. " but this is only version $VERSION";
	}
	else {
	    croak "Unrecognized argument $_";
	}
    }
    unless ($saw_sig) {
	@_ = qw(old-interface-signals);
	goto Arg_loop;
    }
}

sub handler_die {
    croak "Caught a SIG$_[0]";
}

sub handler_traceback {
    package DB;		# To get subroutine args.
    $SIG{'ABRT'} = DEFAULT;
    kill 'ABRT', $$ if $panic++;
    syswrite(STDERR, 'Caught a SIG', 12);
    syswrite(STDERR, $_[0], length($_[0]));
    syswrite(STDERR, ' at ', 4);
    ($pack,$file,$line) = caller;
    syswrite(STDERR, $file, length($file));
    syswrite(STDERR, ' line ', 6);
    syswrite(STDERR, $line, length($line));
    syswrite(STDERR, "\n", 1);

    # Now go for broke.
    for ($i = 1; ($p,$f,$l,$s,$h,$w,$e,$r) = caller($i); $i++) {
        @a = ();
	for $arg (@args) {
	    $_ = "$arg";
	    s/([\'\\])/\\$1/g;
	    s/([^\0]*)/'$1'/
	      unless /^(?: -?[\d.]+ | \*[\w:]* )$/x;
	    s/([\200-\377])/sprintf("M-%c",ord($1)&amp;0177)/eg;
	    s/([\0-\37\177])/sprintf("^%c",ord($1)^64)/eg;
	    push(@a, $_);
	}
	$w = $w ? '@ = ' : '$ = ';
	$a = $h ? '(' . join(', ', @a) . ')' : '';
	$e =~ s/\n\s*\;\s*\Z// if $e;
	$e =~ s/[\\\']/\\$1/g if $e;
	if ($r) {
	    $s = "require '$e'";
	} elsif (defined $r) {
	    $s = "eval '$e'";
	} elsif ($s eq '(eval)') {
	    $s = "eval {...}";
	}
	$f = "file `$f'" unless $f eq '-e';
	$mess = "$w$s$a called from $f line $l\n";
	syswrite(STDERR, $mess, length($mess));
    }
    kill 'ABRT', $$;
}

1;

__END__

=head1 SYNOPSIS

    use sigtrap;
    use sigtrap qw(stack-trace old-interface-signals);	# equivalent
    use sigtrap qw(BUS SEGV PIPE ABRT);
    use sigtrap qw(die INT QUIT);
    use sigtrap qw(die normal-signals);
    use sigtrap qw(die untrapped normal-signals);
    use sigtrap qw(die untrapped normal-signals
		    stack-trace any error-signals);
    use sigtrap 'handler' =&gt; \&amp;my_handler, 'normal-signals';
    use sigtrap qw(handler my_handler normal-signals
    	    	    stack-trace error-signals);

=head1 DESCRIPTION

The B&lt;sigtrap&gt; pragma is a simple interface to installing signal
handlers.  You can have it install one of two handlers supplied by
B&lt;sigtrap&gt; itself (one which provides a Perl stack trace and one which
simply C&lt;die()&gt;s), or alternately you can supply your own handler for it
to install.  It can be told only to install a handler for signals which
are either untrapped or ignored.  It has a couple of lists of signals to
trap, plus you can supply your own list of signals.

The arguments passed to the C&lt;use&gt; statement which invokes B&lt;sigtrap&gt;
are processed in order.  When a signal name or the name of one of
B&lt;sigtrap&gt;'s signal lists is encountered a handler is immediately
installed, when an option is encountered it affects subsequently
installed handlers.

=head1 OPTIONS

=head2 SIGNAL HANDLERS

These options affect which handler will be used for subsequently
installed signals.

=over 4

=item B&lt;stack-trace&gt;

The handler used for subsequently installed signals outputs a Perl stack
trace to STDERR and then tries to dump core.  This is the default signal
handler.

=item B&lt;die&gt;

The handler used for subsequently installed signals calls C&lt;die&gt;
(actually C&lt;croak&gt;) with a message indicating which signal was caught.

=item B&lt;handler&gt; I&lt;your-handler&gt;

I&lt;your-handler&gt; will be used as the handler for subsequently installed
signals.  I&lt;your-handler&gt; can be any value which is valid as an
assignment to an element of C&lt;%SIG&gt;.

=back

=head2 SIGNAL LISTS

B&lt;sigtrap&gt; has a few built-in lists of signals to trap.  They are:

=over 4

=item B&lt;normal-signals&gt;

These are the signals which a program might normally expect to encounter
and which by default cause it to terminate.  They are HUP, INT, PIPE and
TERM.

=item B&lt;error-signals&gt;

These signals usually indicate a serious problem with the Perl
interpreter or with your script.  They are ABRT, BUS, EMT, FPE, ILL,
QUIT, SEGV, SYS and TRAP.

=item B&lt;old-interface-signals&gt;

These are the signals which were trapped by default by the old
B&lt;sigtrap&gt; interface, they are ABRT, BUS, EMT, FPE, ILL, PIPE, QUIT,
SEGV, SYS, TERM, and TRAP.  If no signals or signals lists are passed to
B&lt;sigtrap&gt;, this list is used.

=back

For each of these three lists, the collection of signals set to be
trapped is checked before trapping; if your architecture does not
implement a particular signal, it will not be trapped but rather
silently ignored.

=head2 OTHER

=over 4

=item B&lt;untrapped&gt;

This token tells B&lt;sigtrap&gt; to install handlers only for subsequently
listed signals which aren't already trapped or ignored.

=item B&lt;any&gt;

This token tells B&lt;sigtrap&gt; to install handlers for all subsequently
listed signals.  This is the default behavior.

=item I&lt;signal&gt;

Any argument which looks like a signal name (that is,
C&lt;/^[A-Z][A-Z0-9]*$/&gt;) indicates that B&lt;sigtrap&gt; should install a
handler for that name.

=item I&lt;number&gt;

Require that at least version I&lt;number&gt; of B&lt;sigtrap&gt; is being used.

=back

=head1 EXAMPLES

Provide a stack trace for the old-interface-signals:

    use sigtrap;

Ditto:

    use sigtrap qw(stack-trace old-interface-signals);

Provide a stack trace on the 4 listed signals only:

    use sigtrap qw(BUS SEGV PIPE ABRT);

Die on INT or QUIT:

    use sigtrap qw(die INT QUIT);

Die on HUP, INT, PIPE or TERM:

    use sigtrap qw(die normal-signals);

Die on HUP, INT, PIPE or TERM, except don't change the behavior for
signals which are already trapped or ignored:

    use sigtrap qw(die untrapped normal-signals);

Die on receipt one of an of the B&lt;normal-signals&gt; which is currently
B&lt;untrapped&gt;, provide a stack trace on receipt of B&lt;any&gt; of the
B&lt;error-signals&gt;:

    use sigtrap qw(die untrapped normal-signals
		    stack-trace any error-signals);

Install my_handler() as the handler for the B&lt;normal-signals&gt;:

    use sigtrap 'handler', \&amp;my_handler, 'normal-signals';

Install my_handler() as the handler for the normal-signals, provide a
Perl stack trace on receipt of one of the error-signals:

    use sigtrap qw(handler my_handler normal-signals
    	    	    stack-trace error-signals);

=cut
</pre></body></html>