How can I tell in Linux which process sent my process a signal
Asked Answered
C

4

42

I have a java application that got SIG TERM. I want to know the pid of the process that sent this signal.
Is that possible?

Contortion answered 4/12, 2011 at 19:38 Comment(1)
There's a similar question with possibly better answers, depending on your use case. The question is shell focused unix.stackexchange.com/questions/186200Ultramicrometer
K
43

Two Linux-specific methods are SA_SIGINFO and signalfd(), which allows programs to receive very detailed information about signals sent, including the sender's PID.

  • Call sigaction() and pass to it a struct sigaction which has the desired signal handler in sa_sigaction and the SA_SIGINFO flag in sa_flags set. With this flag, your signal handler will receive three arguments, one of which is a siginfo_t structure containing the sender's PID and UID.

  • Call signalfd() and read signalfd_siginfo structures from it (usually in some kind of a select/poll loop). The contents will be similar to siginfo_t.

Which one to use depends on how your application is written; they probably won't work well outside plain C, and I wouldn't have any hope of getting them work in Java. They are also unportable outside Linux. They also likely are the Very Wrong Way of doing what you are trying to achieve.

Kirima answered 4/12, 2011 at 21:9 Comment(3)
The first method mentioned (sigaction/SA_SIGINFO/siginfo_t) is actually a POSIX standard and are supported on Mac OS, FreeBSD, OpenBSD too, not just Linux.Canvasback
In case someone was searching for this in terms of having caught a signal under gdb: execute p $_siginfo, and then look at si_pid field, it is supposed to contain the sending process PID.Washing
Note that the sender's pid is not always set. Unfortunately, the field si_pid is in a union, so when you think you are reading the pid you might actually read something completely different. For instance, when your program has a segfault, the SIGSEGV signal has no si_pid. Whether or not si_pid is safe to access is described in man sigaction. If you have si_code == SI_USER || si_code == SI_QUEUE then si_pid is set. Otherwise it gets complicated.Socioeconomic
G
14

I also needed to identify the signal sender in a program, so I took grawity's answer, and used it in my program, it works well.

Here's the sample code:

send_signal_raise.c

// send signal to self test - raise()

#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

static int int_count = 0, max_int = 5;
static struct sigaction siga;

static void multi_handler(int sig, siginfo_t *siginfo, void *context) {
    // get pid of sender,
    pid_t sender_pid = siginfo->si_pid;

    if(sig == SIGINT) {
        int_count++;
        printf("INT(%d), from [%d]\n", int_count, (int)sender_pid);
        return;
    } else if(sig == SIGQUIT) {
        printf("Quit, bye, from [%d]\n", (int)sender_pid);
        exit(0);
    }

    return;
}

int raise_test() {
    // print pid
    printf("process [%d] started.\n", (int)getpid());

    // prepare sigaction
    siga.sa_sigaction = *multi_handler;
    siga.sa_flags |= SA_SIGINFO; // get detail info

    // change signal action,
    if(sigaction(SIGINT, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }
    if(sigaction(SIGQUIT, &siga, NULL) != 0) {
        printf("error sigaction()");
        return errno;
    }

    // use "ctrl + c" to send SIGINT, and "ctrl + \" to send SIGQUIT,
    int sig;
    while(1) {
        if(int_count < max_int) {
            sig = SIGINT;
        } else {
            sig  = SIGQUIT;
        }
        raise(sig); // send signal to itself,

        sleep(1); // sleep a while, note that: SIGINT will interrupt this, and make program wake up,
    }

    return 0;
}

int main(int argc, char *argv[]) {
    raise_test();
    return 0;
}

Compile:

gcc -pthread -Wall send_signal_raise.c

Execute:

./a.out

What it does:

The program sends SIGINT to itself 10 times, before sending SIGQUIT to terminate itself.

Also, during its execution, press CTRL+C to send SIGINT, or CTRL+\ to send SIGQUIT which would terminate the program by hand.

The program could successfully identify who sent the signal(s).

Guarani answered 25/7, 2015 at 5:54 Comment(0)
M
2

BCC includes the killsnoop utility. It requires a kernel with BPF support.

Excerpt from killsnoop (8) man-page:

       killsnoop  traces  the  kill()  syscall, to show signals sent via this method. This may be
       useful to troubleshoot  failing  applications,  where  an  unknown  mechanism  is  sending
       signals.

       This  works by tracing the kernel sys_kill() function using dynamic tracing, and will need
       updating to match any changes to this function.

       This makes use of a Linux 4.5 feature (bpf_perf_event_output()); for  kernels  older  than
       4.5, see the version under tools/old, which uses an older mechanism.

       Since this uses BPF, only the root user can use this tool.
Mcnulty answered 17/6, 2020 at 17:11 Comment(3)
I have a signal (37 (SIGRTMIN+3) ) which is being sent to a process that killsnoop doesn't log. Can there be a signal that doesn't flow through the syscalls that it monitors?Whiteeye
Seems like sigqueue uses a different syscallWhiteeye
After adding also sigqueue to killsnoop I still get nothingWhiteeye
P
0

No, Signals are not intended as an interprocess communication channel. As far as I am aware, there is no PID passed. The sending PID is irrelevant for all of the uses I have seen for signals. You can be relatively sure that the processes sending the signal either had root privileges, or belonged to the same UID as your process.

It is possible that the process that sent the signal does not exist anymore. If the kill command was used rather than the shell built-in, it is almost certain the process no longer exists.

From the Java side this is even more difficult. The process runs in a Java Virtual Machine, which is abstracted from the Operating System. Not all Operating System concepts exist with this machine.

Persse answered 4/12, 2011 at 20:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.