Usa sigaction con SA_SIGINFO establecido en sa_flags.
código Prototipo:
#define _GNU_SOURCE 1 /* To pick up REG_RIP */
#include <stdio.h>
#include <signal.h>
#include <assert.h>
static void
handler(int signo, siginfo_t *info, void *context)
{
const ucontext_t *con = (ucontext_t *)context;
/* I know, never call printf from a signal handler. Meh. */
printf("IP: %lx\n", con->uc_mcontext.gregs[REG_RIP]);
}
int
main(int argc, char *argv[])
{
struct sigaction sa = { };
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
assert(sigaction(SIGINT, &sa, NULL) == 0);
for (;;);
return 0;
}
Ejecutar y golpeó Ctrl-C. (Use Ctrl- \ para terminar ...)
Esto es para x86_64. Para 32 bits x86, use REG_EIP
en lugar de REG_RIP
.
[editar]
Por supuesto, si usted está realmente en una función de biblioteca (como printf
) o una llamada al sistema (como write
), el registro PIR/EIP podría señalar alguna parte divertida ...
Es posible que desee utilizar libunwind para rastrear la pila.
¡Muchas gracias! ¡Esto es lo que necesito! – flyingbin
printf generalmente no es reentrante, así que si usted está en printf cuando recibe la señal, esto probablemente imprimirá basura o se bloqueará ... –
@Chris: Sí, lo sé. Este programa de ejemplo funciona bien por sí mismo (probablemente), y fue la forma más fácil de demostrar el principio.Pero es por eso que incluí el comentario y lo llamé "código de prototipo" :-) – Nemo