Подтвердить что ты не робот

Как я могу сказать в Linux, какой процесс отправил мой процесс сигнал

У меня есть приложение Java, которое получило SIG TERM. Я хочу знать pid процесса, который отправил этот сигнал.
Возможно ли это?

4b9b3361

Ответ 1

Два конкретных для Linux метода: SA_SIGINFO и signalfd(), что позволяет программам получать очень подробную информацию о посылаемых сигналах, включая идентификатор отправителя.

  • Вызвать sigaction() и передать ему a struct sigaction, который имеет желаемый обработчик сигнала в sa_sigaction, а SA_SIGINFO флаг в sa_flags. С помощью этого флага ваш обработчик сигналов получит три аргумента, одна из которых представляет собой структуру siginfo_t, содержащую PID и UID отправителя.

  • Вызовите signalfd() и прочитайте структуры signalfd_siginfo (обычно в каком-то цикле выбора/опроса). Содержимое будет похоже на siginfo_t.

Какой из них использовать, зависит от того, как написано ваше приложение; они, вероятно, не будут хорошо работать за пределами обычного C, и у меня не будет никакой надежды заставить их работать на Java. Они также недоступны вне Linux. Они также, вероятно, очень неправильный способ сделать то, что вы пытаетесь достичь.

Ответ 2

Мне также нужно было идентифицировать отправителя сигнала в программе, поэтому я взял grawity answer и использовал его в своей программе, он хорошо работает.

Здесь пример кода:

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

Что он делает:

Программа отправляет SIGINT себе 10 раз, перед отправкой SIGQUIT для завершения.

Кроме того, во время выполнения нажмите CTRL + C, чтобы отправить SIGINT, или CTRL + \, чтобы отправить SIGQUIT, который завершит работу программы вручную.

Программа может успешно идентифицировать, кто отправил сигнал (ы).

Ответ 3

Нет. Сигналы не предназначены как канал связи между процессами. Насколько мне известно, PID не передается. Передающий PID не имеет значения для всех применений, которые я видел для сигналов. Вы можете быть уверены, что процессы, отправляющие сигнал, либо имеют права root, либо принадлежат к тому же UID, что и ваш процесс.

Возможно, что процесс, отправивший сигнал, больше не существует. Если команда kill использовалась, а не встроенная оболочка, почти наверняка процесс больше не существует.

Со стороны Java это еще сложнее. Процесс выполняется на виртуальной машине Java, которая абстрагируется от операционной системы. Не все концепции операционной системы существуют с этой машиной.