How, in Perl 5, can I get the pid of the process who sent me a signal?

走远了吗. 提交于 2019-11-30 07:51:18

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.

#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.


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.

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!