在信号处理程序,怎么知道那里的程序被中断? [英] In a signal handler, how to know where the program is interrupted?

查看:356
本文介绍了在信号处理程序,怎么知道那里的程序被中断?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在x86(无论是64位或32位)的Linux -
例如:

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
    ...
}

在signal_handler,我们怎么能知道我们是在以printf的主要打断()?

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

推荐答案

使用的sigaction与 SA_SIGINFO在其中sa_flags设置。

Use sigaction with SA_SIGINFO set in sa_flags.

原型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;
}

运行它,按<大骨节病>按Ctrl-C 。 (使用<大骨节病>按Ctrl - \\ 终止...)

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

这是x86_64的。对于32位x86,使用 REG_EIP 而不是 REG_RIP

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

当然,如果你实际上是在一个库函数(如的printf )或系统调用(如)时,RIP / EIP寄存器可能指向有趣的地方...

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...

您可能需要使用 libunwind 抓取堆栈。

You might want to use libunwind to crawl the stack.

这篇关于在信号处理程序,怎么知道那里的程序被中断?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆