如何,在Perl 5,我可以得到的过程谁给我一个信号的PID?

前端之家收集整理的这篇文章主要介绍了如何,在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 %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;
}

这打印出来的东西

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 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;

但是处理程序仍然只接收一个参数(信号)。如何获得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获取

原文链接:https://www.f2er.com/Perl/173438.html

猜你在找的Perl相关文章