In a signal handler, how to know where the program

2020-06-12 02:34发布

On x86 (either 64-bit or 32-bit) Linux -- for example:

void signal_handler(int) {
   // want to know where the program is interrupted ...
}

int main() {
    ...
    signal(SIGALRM, signal_handler);
    alarm(5);
    ...
    printf(...); <------- at this point, we trigger signal_handler
    ...
}

In signal_handler, how can we know we are interrupted at printf in main()?

4条回答
淡お忘
2楼-- · 2020-06-12 02:53

Workaround idea: if there are only a small number of places which can trigger a signal handler or you are only interested in which bigger block it happened you could maintain that in a variable.

entered = 1; // or entered = ENTER_PRINTF1;
printf(....);
查看更多
贪生不怕死
3楼-- · 2020-06-12 02:55

Use sigaction with SA_SIGINFO set in sa_flags.

Prototype code:

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

Run it and hit Ctrl-C. (Use Ctrl-\ to terminate...)

This is for x86_64. For 32-bit x86, use REG_EIP instead of REG_RIP.

[edit]

Of course, if you are actually in a library function (like printf) or a system call (like write), the RIP/EIP register might point somewhere funny...

You might want to use libunwind to crawl the stack.

查看更多
家丑人穷心不美
4楼-- · 2020-06-12 02:57

Depending on your OS / Platform, it could be in a variety of areas:

  • On the current stack a set number of registers deep
  • On an/the interrupt stack
  • Within some sort of callback associated with your signal routine...

Without having additional info, I don't think we can track this much further. Adding a C/C++ tag to your might generate more responses and views.

查看更多
劫难
5楼-- · 2020-06-12 03:03

In signal_handler, how can we know we are interrupted at printf in main()? You can't, at least not from a C, C++, or POSIX perspective. Your operating system may provide OS-specific calls that let you poke at the stack. That's more than a bit dubious, though.

With timer-based signals, which instruction triggered the signal is a toss of the coin.

查看更多
登录 后发表回答