ti-enxame.com

Como posso saber no Linux qual processo enviou um sinal ao meu processo

Eu tenho um Java aplicativo que obteve SIG TERM. Eu quero saber o pid do processo que enviou este sinal.
Isso é possível?

28
oshai

Dois métodos específicos do Linux são SA_SIGINFO e signalfd() , que permite que os programas recebam muito informações detalhadas sobre os sinais enviados, incluindo o PID do remetente.

  • Ligue para sigaction() e passe para ele um struct sigaction Que possui o manipulador de sinal desejado em sa_sigaction E o sinalizador SA_SIGINFO Em sa_flags Definido. Com esse sinalizador, seu manipulador de sinal receberá três argumentos , um dos quais é uma estrutura siginfo_t Que contém o PID e o UID do remetente.

  • Chame signalfd() e leia as estruturas signalfd_siginfo (Normalmente em algum tipo de loop de seleção/pesquisa). O conteúdo será semelhante a siginfo_t.

Qual usar depende de como seu aplicativo é gravado; eles provavelmente não funcionarão bem fora do C, e eu não teria nenhuma esperança de fazê-los funcionar em Java. Eles também não são portáveis ​​fora do Linux. Eles também provavelmente são a maneira muito errada de fazer o que você está tentando alcançar.

31
grawity

Eu também precisava identificar o remetente do sinal em um programa, então peguei o resposta do grawity e o usei no meu programa, ele funciona bem.

Aqui está o código de exemplo:

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;
}

Compilar:

gcc -pthread -Wall send_signal_raise.c

Execute:

./a.out

O que faz:

O programa envia SIGINT para si mesmo 10 vezes, antes de enviar SIGQUIT para terminar automaticamente.

Além disso, durante sua execução, pressione CTRL+C para enviar SIGINT, ou CTRL+\ para enviar SIGQUIT que encerraria o programa manualmente.

O programa conseguiu identificar com êxito quem enviou o (s) sinal (es).

9
Eric Wang

Não, os sinais não se destinam a ser um canal de comunicação entre processos. Tanto quanto sei, não há PID passado. O PID de envio é irrelevante para todos os usos que vi nos sinais. Você pode estar relativamente certo de que os processos que enviam o sinal tinham privilégios de root ou pertenciam ao mesmo UID do seu processo.

É possível que o processo que enviou o sinal não exista mais. Se o comando kill foi usado em vez do interno do Shell, é quase certo que o processo não existe mais.

Do lado Java, isso é ainda mais difícil. O processo é executado em uma máquina virtual Java, que é abstraída do sistema operacional. Nem todos os conceitos de sistema operacional existe com esta máquina.

1
BillThor