I want to specify a signal handler in Perl, but using the number, not the name. Is this possible in a succinct way? The lack of symmetry with kill particularly sticks out. For example, instead of
$SIG{USR2} = \&myhandler;
I'd like to say
$SIG{12} = \&myhandler;
The best I have at the moment is to "use Config" and poke around in $Config{sig_name}, based on the code in perldoc perlipc. This is verbose and seems needlessly complicated.
Rationale: I've wanted this in two cases recently.
1: I'm being started by a buggy parent process who incorrectly sets signals I care about to ignore, and I want to just reset everything to default. eg http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=679630 The goal would be something simple and brute force like:
foreach my $i (1..32) { $SIG{$i} = 'DEFAULT'; }
2: I'm writing a thin, as-invisible-as-possible wrapper script. If the program I'm wrapping exits with a signal, I want to exit with that same signal. However, I capture a few signals, so I need to clear my own signal handler to ensure i actually exit instead of entering my signal handler. My goal is to write something brief like this:
$ret = system("./other-program");
$SIG{$ret & 127} = 'DEFAULT';
kill $ret & 127, $$;
First question:
use Config qw( %Config );
my @sig_name_by_num;
@sig_name_by_num[ split(' ', $Config{sig_num}) ] = split(' ', $Config{sig_name});
$SIG{$sig_name_by_num[12]} = \&handler;
Second question:
use Config qw( %Config );
$SIG{$_} = 'DEFAULT' for split ' ', $Config{sig_name};
-or-
$SIG{$_} = 'DEFAULT' for keys %SIG;
-or-
$_ = 'DEFAULT' for values %SIG;
Third question
use Config qw( %Config );
my @sig_name_by_num;
@sig_name_by_num[ split(' ', $Config{sig_num}) ] = split(' ', $Config{sig_name});
my $sig_num = $? & 0x7F;
$SIG{$sig_name_by_num[$sig_num]} = 'DEFAULT';
kill($sig_num => $$);
If you just want to set all signals at once, you don't need to know their numbers:
$SIG{$_} = 'DEFAULT' for keys %SIG;
Using $Config{sig_name}/$Config{sig_num}
is the only portable way to map signal numbers to names, but a quick and dirty way that works on many Unix-y systems is
$sig_name = qx(kill -l $sig_num);
($sig_name
will then have a trailing newline, so in practice you'd want to do something like
chomp($sig_name = qx(kill -l $sig_num));
($sig_name) = qx(kill -l $sig_num) =~ /(\S+)/;
)
That's not necessarily any more concise than using %Config
, though, unless you turned it into a function.
sub sig_no { chomp(my ($sig_no = qx(kill -l $_[0])); $sig_no }
$SIG{ sig_no($ret & 127) } = 'DEFAULT';
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With