In C, I can say
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int continue_running = 1;
void handler(int signal, siginfo_t* info, void* data) {
printf("got signal %d from process %d running as user %d\n",
signal, info->si_pid, info->si_uid);
continue_running = 0;
}
int main(int argc, char** argv) {
struct sigaction sa;
sigset_t mask;
sigemptyset(&mask);
sa.sa_sigaction = &handler;
sa.sa_mask = mask;
sa.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &sa, NULL);
printf("pid is %d\n", getpid());
while (continue_running) { sleep(1); };
return 0;
}
This prints out something like
pid is 31980
got signal 15 from process 31985 running as user 1000
when sent a SIGTERM from process 31985.
I can write similar Perl 5 code using POSIX::sigaction:
#!/usr/bin/perl
use strict;
use warnings;
use POSIX;
use Data::Dumper;
my $sigset = POSIX::SigSet->new;
$sigset->emptyset;
my $sa = POSIX::SigAction->new(
sub { print "caught signal\n" . Dumper \@_; $a = 0 },
$sigset,
);
$sa->flags(POSIX::SA_SIGINFO);
$sa->safe(1); #defer the signal until we are in a safe place in the intrepeter
POSIX::sigaction(POSIX::SIGTERM, $sa);
print "$$\n";
$a = 1;
sleep 1 while $a;
But the handler still only receives one argument (the signal). How can I get at siginfo_t structure? Do have to write my own XS code that sets up its own handler and then passes the information on to a Perl callback? Will writing my own handler in XS screw up the interpreter in some way?
sighandler(found inmg.c) is the wrapper around the Perl signal handler sub. As you can see, it is capabable of sending the information you want to the Perl signal handler sub.The information you want would be in the last parameter, although you’d have to unpack
*sipyourself Perl-side. The catch is that the above code isn’t getting excercised. Specifically,sipis alwaysNULL.Under unsafe signals,
sighandleris called fromcsighandler, Perl’s C-level signal handler. It currently doesn’t pass on the pertinent information tosignalhandler, but that’s easily fixed.Sample run:
Under safe signals,
sighandleris called fromdespatch_signals(sic) viaPERL_ASYNC_CHECK. Unfortunately, the*sippreviously received bycsighandleris no longer available. To fix this,csighandlerwould have to queue a copy of*sipfordespatch_signalsto fetch.