In C, I can say
在C中,我可以说
#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.
当从过程31985发送SIGTERM时。
I can write similar Perl 5 code using POSIX::sigaction
:
我可以使用POSIX :: sigaction编写类似的Perl 5代码:
#!/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?
但处理程序仍然只接收一个参数(信号)。我怎样才能获得siginfo_t结构?是否必须编写自己的XS代码来设置自己的处理程序,然后将信息传递给Perl回调?在XS中编写自己的处理程序会以某种方式搞砸解释器吗?
1 个解决方案
#1
19
sighandler
(found in mg.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.
sighandler(在mg.c中找到)是Perl信号处理程序子包围的包装器。如您所见,它可以将您想要的信息发送到Perl信号处理程序子。
#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
{
struct sigaction oact;
if (sigaction(sig, 0, &oact) == 0 && oact.sa_flags & SA_SIGINFO) {
if (sip) {
HV *sih = newHV();
SV *rv = newRV_noinc(MUTABLE_SV(sih));
/* The siginfo fields signo, code, errno, pid, uid,
* addr, status, and band are defined by POSIX/SUSv3. */
(void)hv_stores(sih, "signo", newSViv(sip->si_signo));
(void)hv_stores(sih, "code", newSViv(sip->si_code));
#if 0 /* XXX TODO: Configure scan for the existence of these, but even that does not help if the SA_SIGINFO is not implemented according to the spec. */
hv_stores(sih, "errno", newSViv(sip->si_errno));
hv_stores(sih, "status", newSViv(sip->si_status));
hv_stores(sih, "uid", newSViv(sip->si_uid));
hv_stores(sih, "pid", newSViv(sip->si_pid));
hv_stores(sih, "addr", newSVuv(PTR2UV(sip->si_addr)));
hv_stores(sih, "band", newSViv(sip->si_band));
#endif
EXTEND(SP, 2);
PUSHs(rv);
mPUSHp((char *)sip, sizeof(*sip));
}
}
}
}
The information you want would be in the last parameter, although you'd have to unpack *sip
yourself Perl-side. The catch is that the above code isn't getting excercised. Specifically, sip
is always NULL
.
你想要的信息将在最后一个参数中,尽管你必须解包*自己啜饮Perl端。问题是上面的代码没有得到执行。具体来说,sip始终为NULL。
Under unsafe signals, sighandler
is called from csighandler
, Perl's C-level signal handler. It currently doesn't pass on the pertinent information to signalhandler
, but that's easily fixed.
在不安全的信号下,sighandler是从csighandler调用的,这是Perl的C级信号处理程序。它目前没有将相关信息传递给signalhandler,但这很容易修复。
-Perl_csighandler(int sig, siginfo_t *sip PERL_UNUSED_DECL, void *uap PERL_UNUSED_DECL)
+Perl_csighandler(int sig, siginfo_t *sip, void *uap PERL_UNUSED_DECL)
- (*PL_sighandlerp)(sig, NULL, NULL);
+ (*PL_sighandlerp)(sig, sip, NULL);
Sample run:
样品运行:
$ PERL_SIGNALS=unsafe ./perl -Ilib a.pl
31213
caught signal
$VAR1 = [
'TERM',
{
'code' => 0,
'signo' => 15
},
'...*sip as "packed/binary" string...'
];
Under safe signals, sighandler
is called from despatch_signals
(sic) via PERL_ASYNC_CHECK
. Unfortunately, the *sip
previously received by csighandler
is no longer available. To fix this, csighandler
would have to queue a copy of *sip
for despatch_signals
to fetch.
在安全信号下,通过PERL_ASYNC_CHECK从despatch_signals(sic)调用sighandler。不幸的是,之前由csighandler收到的* sip已不再可用。要解决此问题,csighandler必须将用于despatch_signals的* sip副本排队到fetch。
#1
19
sighandler
(found in mg.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.
sighandler(在mg.c中找到)是Perl信号处理程序子包围的包装器。如您所见,它可以将您想要的信息发送到Perl信号处理程序子。
#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
{
struct sigaction oact;
if (sigaction(sig, 0, &oact) == 0 && oact.sa_flags & SA_SIGINFO) {
if (sip) {
HV *sih = newHV();
SV *rv = newRV_noinc(MUTABLE_SV(sih));
/* The siginfo fields signo, code, errno, pid, uid,
* addr, status, and band are defined by POSIX/SUSv3. */
(void)hv_stores(sih, "signo", newSViv(sip->si_signo));
(void)hv_stores(sih, "code", newSViv(sip->si_code));
#if 0 /* XXX TODO: Configure scan for the existence of these, but even that does not help if the SA_SIGINFO is not implemented according to the spec. */
hv_stores(sih, "errno", newSViv(sip->si_errno));
hv_stores(sih, "status", newSViv(sip->si_status));
hv_stores(sih, "uid", newSViv(sip->si_uid));
hv_stores(sih, "pid", newSViv(sip->si_pid));
hv_stores(sih, "addr", newSVuv(PTR2UV(sip->si_addr)));
hv_stores(sih, "band", newSViv(sip->si_band));
#endif
EXTEND(SP, 2);
PUSHs(rv);
mPUSHp((char *)sip, sizeof(*sip));
}
}
}
}
The information you want would be in the last parameter, although you'd have to unpack *sip
yourself Perl-side. The catch is that the above code isn't getting excercised. Specifically, sip
is always NULL
.
你想要的信息将在最后一个参数中,尽管你必须解包*自己啜饮Perl端。问题是上面的代码没有得到执行。具体来说,sip始终为NULL。
Under unsafe signals, sighandler
is called from csighandler
, Perl's C-level signal handler. It currently doesn't pass on the pertinent information to signalhandler
, but that's easily fixed.
在不安全的信号下,sighandler是从csighandler调用的,这是Perl的C级信号处理程序。它目前没有将相关信息传递给signalhandler,但这很容易修复。
-Perl_csighandler(int sig, siginfo_t *sip PERL_UNUSED_DECL, void *uap PERL_UNUSED_DECL)
+Perl_csighandler(int sig, siginfo_t *sip, void *uap PERL_UNUSED_DECL)
- (*PL_sighandlerp)(sig, NULL, NULL);
+ (*PL_sighandlerp)(sig, sip, NULL);
Sample run:
样品运行:
$ PERL_SIGNALS=unsafe ./perl -Ilib a.pl
31213
caught signal
$VAR1 = [
'TERM',
{
'code' => 0,
'signo' => 15
},
'...*sip as "packed/binary" string...'
];
Under safe signals, sighandler
is called from despatch_signals
(sic) via PERL_ASYNC_CHECK
. Unfortunately, the *sip
previously received by csighandler
is no longer available. To fix this, csighandler
would have to queue a copy of *sip
for despatch_signals
to fetch.
在安全信号下,通过PERL_ASYNC_CHECK从despatch_signals(sic)调用sighandler。不幸的是,之前由csighandler收到的* sip已不再可用。要解决此问题,csighandler必须将用于despatch_signals的* sip副本排队到fetch。