У меня есть приложение Java, которое получило SIG TERM
. Я хочу знать pid процесса, который отправил этот сигнал.
Возможно ли это?
Как я могу сказать в Linux, какой процесс отправил мой процесс сигнал
Ответ 1
Два конкретных для Linux метода: SA_SIGINFO
и signalfd()
, что позволяет программам получать очень подробную информацию о посылаемых сигналах, включая идентификатор отправителя.
-
Вызвать
sigaction()
и передать ему astruct 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, которая абстрагируется от операционной системы. Не все концепции операционной системы существуют с этой машиной.