Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Perl 5中,如何获取发送信号的进程的pid?_Perl_Signals - Fatal编程技术网

在Perl 5中,如何获取发送信号的进程的pid?

在Perl 5中,如何获取发送信号的进程的pid?,perl,signals,Perl,Signals,在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,

在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;
}
从进程31985发送
SIGTERM

我可以使用
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;
但是处理程序仍然只接收一个参数(信号)。我如何在
siginfo\u t
structure获取信息?是否必须编写自己的XS代码来设置自己的处理程序,然后将信息传递给Perl回调?在XS中编写自己的处理程序会在某种程度上破坏解释器吗

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));
            }
        }
    }
}
您想要的信息将在最后一个参数中,尽管您必须在Perl端解包
*sip
。问题是上面的代码没有得到执行。具体来说,
sip
总是
NULL


在不安全信号下,
sighandler
从Perl的C级信号处理程序
csighandler
调用。它目前没有将相关信息传递给
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\u ASYNC\u CHECK
dispatch\u signals
(sic)调用
sighandler
。不幸的是,
csighandler
以前接收到的
*sip
不再可用。要解决此问题,
csighandler
必须将
*sip
的副本排队,以便
发送信号
提取。

我希望我能多次对此进行投票。这是一个非常好的问题。您看过POSIX模块中现有的XS代码了吗?我没有,但我打赌这就是你问题的答案所在。至于搞糟解释器,你知道解释器循环的“安全信号”改变了吗?@tchrist是的,我知道在5.8行的某个点上发生的改变。这正是我所担心的。我不知道如何与那些东西的工作方式相衔接。阅读POSIX XS的内容可能是一条出路。我希望有人已经为我做了艰苦的工作。如果@tchrist喜欢,那对我来说就足够了:+1是的,我一直在研究,如果定义了
SA_siginfo
,并且启用了
特性
pragma,如何使Perl 5.15始终在hashref中传递第二个带有siginfo_t数据的arg给信号处理程序。显然,我在研究5.8.8代码,正如您的代码所示,5.14似乎已经有很多需要做的事情。现在我的问题是为什么在5.14中它对我不起作用。我疯了吗,或者那代码毫无意义?它正在创建
sih
,在我看来,它就像一个匿名hashref,但它从未使用过它。它将
sip
推到堆栈上。别担心,我疯了,
rv
是对
sih
的引用,它被
push
推到堆栈上@Chas。欧文斯,对于你的脚本,
oact.sa_flags&sa_SIGINFO
4
,但是
sip
NULL
$ PERL_SIGNALS=unsafe ./perl -Ilib a.pl
31213
caught signal
$VAR1 = [
          'TERM',
          {
            'code' => 0,
            'signo' => 15
          },
          '...*sip as "packed/binary" string...'
        ];