gpt4 book ai didi

perl - 在 Perl 5 中,我如何获得向我发送信号的进程的 pid?

转载 作者:行者123 更新时间:2023-12-03 07:35:20 25 4
gpt4 key购买 nike

在 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 时。

我可以使用 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_t 结构?是否必须编写自己的 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

<小时/>

在不安全信号下,从 Perl 的 C 级信号处理程序 csighandler 调用 sighandler。目前它不会将相关信息传递给 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...'
];
<小时/>

在安全信号下,sighandler 通过 PERL_ASYNC_CHECKdespatch_signals(原文如此)调用。不幸的是,之前由 csighandler 收到的 *sip 不再可用。要解决此问题,csighandler 必须将 *sip 的副本排队以供 despatch_signals 获取。

关于perl - 在 Perl 5 中,我如何获得向我发送信号的进程的 pid?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6296374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com