lakshmananindia has asked for the wisdom of the Perl Monks concerning the following question:

I have a signal handler to handle INT signal.
Now I need to take the process ID, which sends INT signal.
Assume that my process is A.
Process B sent INT signal to process A.
Now in the handler, I want to take the process ID of B.
In C I did this.
But I don't know in Perl.
How can I do that? Please Help.

Replies are listed 'Best First'.
Re: Signal Handler
by gone2015 (Deacon) on Dec 05, 2008 at 13:20 UTC

    You can reach down into the signal handling using stuff provided by POSIX module.

      But according to man perlvar

      If your system has the sigaction() function then signal handlers are installed using it. This means you get reliable signal handling.

      My system has sigaction. So why I need to use POSIX. Please clarify me on this.

        The standard Perl signal handlers are only given the received signal name as argument. There is no way to get the PID of the process that sent the signal.

        If you use POSIX::sigaction you can set the SA_SIGINFO flag so that your handler receives a hash which includes keys pid and uid (but note the warning in POSIX::sigaction that many systems do not provide this information) and the binary content of the siginfo structure.

      ...which, presumably, is essentially what he did in C - good call oshalla.

      A user level that continues to overstate my experience :-))
Re: Signal Handler
by almut (Canon) on Dec 05, 2008 at 14:38 UTC

    The theory is described here, but in my experience this doesn't work as advertised...

    For example, this is what I get on the Linux box (SuSE 10.2) I'm sending this from:

    #!/usr/local/perl/5.10.0/bin/perl use strict; use warnings; use POSIX; use Data::Dumper; $Data::Dumper::Useqq = 1; my $inf; my $sender_pid; POSIX::sigaction( SIGINT, POSIX::SigAction->new( sub { $inf = Dumper \@_; $sender_pid = unpack "x16S", $_[2]; # <-- }, 0, POSIX::SA_SIGINFO ), ); kill 'INT', $$; print $inf; print "Sender PID: $sender_pid\n"; print "Own PID: $$\n"; __END__ $VAR1 = [ "INT", { "code" => 0, "signo" => 2 }, "\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0RQ\0\0005\4\0\0\270\273}\0\ +0\0\0\0`\257i\0\0\0\0\0\3342E\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 +\0\370\25e\0\0\0\0\0\30 e\0\0\0\0\0\1\0\0\0\0\0\0\0\r\0\0\0\0\0\0\0\3 +60b8\213\377\177\0\0\370b8\213\377\177\0\0\1\0\0\0\0\0\0\0\3IM\0\0\0\ +0\0" ]; Sender PID: 20818 (as we're sending the signal ourself, the sender i +s $$) Own PID: 20818

    Ideally - as I'm reading the docs - there should also be hash fields for 'pid' (the process id generating the signal), 'uid', etc. — not available in this case, though.

    With a bit of luck (and reading through your system's siginfo.h — (e.g. /usr/include/asm-generic/siginfo.h on my system)), you might be able to extract the relevant info from the raw siginfo struct dump...

    Update:  unpack "x16S", ... looks promising — at least in my case, it extracts the appropriate PID  (see $sender_pid in the above updated snippet).  But be sure to test its portability, before you make this a vital part of your application...! :)

      Thanks for our reply. I executed the code that you posted.
      But I got only the signal name.
      $VAR1 = [ "INT" ]; Sender PID: Own PID: 2784

      I am using debian, and my system supports sigaction(2). Now I need to know what will be the problem. Please help.

        Sorry, forgot to mention explicitly that this only works starting with Perl 5.10.0 — AFAIK, older versions only ever provide the signal name (I get the same output as you with 5.8.8).

        Update: FWIW, this is the respective code snippet from mg.c (line 2854) in the Perl 5.10.0 sources:

        #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((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((SV*)rv); PUSHs(newSVpvn((char *)sip, sizeof(*sip))); } } } #endif

        I can't find any entry in the Changes file when this has been added, but it's definitely not there in 5.8.8.   (Note the "#if 0 /* XXX TODO:...", btw, which wraps the "pid" code.)