如何,在Perl 5,我可以得到的过程谁给我一个信号的PID?
在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 %dn",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 %dn",getpid()); while (continue_running) { sleep(1); }; return 0; } 这打印出来的东西 pid is 31980 got signal 15 from process 31985 running as user 1000 当从过程31985发送SIGTERM时。 我可以写类似的Perl 5代码使用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 signaln" . 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; 但是处理程序仍然只接收一个参数(信号)。如何获得siginfo_t结构?是否必须编写自己的XS代码设置自己的处理程序,然后将信息传递到Perl回调?在XS中编写自己的处理程序在某种程度上解开了解释器? 解决方法
sighandler(在mg.c中)是Perl信号处理程序子程序的包装器。正如你可以看到,它是能够发送你想要的信息到Perl信号处理程序子。
#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) { struct sigaction oact; if (sigaction(sig,&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)); } } } } 你想要的信息将在最后一个参数,虽然你必须解压* sip自己的Perl端。抓住的是,上面的代码没有得到excercised。具体来说,sip总是NULL。 在不安全信号下,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); 样品运行: $ PERL_SIGNALS=unsafe ./perl -Ilib a.pl 31213 caught signal $VAR1 = [ 'TERM',{ 'code' => 0,'signo' => 15 },'...*sip as "packed/binary" string...' ]; 在安全信号下,通过PERL_ASYNC_CHECK从despatch_signals(sic)调用sigandler。不幸的是,先前由csighandler接收的* sip不再可用。要解决这个问题,csighandler必须将* sip的副本排队等待despatch_signals获取。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |