También necesitaba identificar el remitente de la señal en un programa, así que tomé la respuesta de grawity y la usé en mi programa, funciona bien.
Aquí está el código de muestra:
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
Ejecutar:
./a.out
Qué hace:
El programa envía SIGINT
a sí mismo 10 veces, antes de enviar SIGQUIT
terminarse a sí mismo.
Además, durante su ejecución, presione CTRL +C enviar SIGINT
o CTRL +\ enviar SIGQUIT
que terminaría el programa a mano.
El programa pudo identificar con éxito quién envió la(s) señal(es).
BCC incluye el killsnoop
utilidad. Requiere un kernel con soporte BPF.
Extracto de la página del manual de killsnoop (8):
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.
Dos métodos específicos de Linux son SA_SIGINFO
y signalfd()
, que permite que los programas reciban muy información detallada sobre las señales enviadas, incluido el PID del remitente.
-
Llama al
sigaction()
y pasarle unstruct sigaction
que tiene el controlador de señal deseado ensa_sigaction
y elSA_SIGINFO
bandera ensa_flags
establecer. Con esta bandera, su controlador de señal recibirá tres argumentos, uno de los cuales es unsiginfo_t
estructura que contiene el PID y el UID del remitente. -
Llama al
signalfd()
y leesignalfd_siginfo
estructuras a partir de él (normalmente en algún tipo de bucle de selección/sondeo). El contenido será similar asiginfo_t
.
Cuál usar depende de cómo esté escrita su aplicación; probablemente no funcionarán bien fuera de C simple, y no tendría ninguna esperanza de que funcionen en Java. Tampoco son portátiles fuera de Linux. También es probable que sean la forma muy incorrecta de hacer lo que está tratando de lograr.