如何在信号处理程序中使用"sigaltstack"?

for*_*ppy 10 c posix signals

有谁知道如何在真正的信号处理程序中使用sigaltstack,一个简单但完整的代码可能对我很有帮助!先感谢您!

R..*_*R.. 18

这是一个sigaltstack用于捕获无限递归的最小示例程序.如果你注释掉sigaltstack调用或SA_ONSTACK标志,信号处理程序将无法运行,因为它没有剩余堆栈,程序将崩溃.

#define _XOPEN_SOURCE 700
#include <signal.h>
#include <unistd.h>
void handler(int sig)
{
    write(2, "stack overflow\n", 15);
    _exit(1);
}
unsigned infinite_recursion(unsigned x) {
    return infinite_recursion(x)+1;
}
int main()
{
    static char stack[SIGSTKSZ];
    stack_t ss = {
        .ss_size = SIGSTKSZ,
        .ss_sp = stack,
    };
    struct sigaction sa = {
        .sa_handler = handler,
        .sa_flags = SA_ONSTACK
    };
    sigaltstack(&ss, 0);
    sigfillset(&sa.sa_mask);
    sigaction(SIGSEGV, &sa, 0);
    infinite_recursion(0);
}
Run Code Online (Sandbox Code Playgroud)

更复杂的用法可能实际上siglongjmp是跳出信号处理程序并返回到可以避免无限递归的点.如果正在使用异步信号不安全库调用,或者您的数据可能处于不安全/不可恢复状态,则无效,但如果您执行纯算术计算,则它可能有效.

对于信号处理程序而言,更好的任务可能是执行尚未保存到磁盘的任何有价值/关键数据的紧急转储.如果你不能调用async-signal-unsafe函数,这可能很难,但是如果你付出一些努力,通常是可能的.

  • 它适用于我(修复一个拼写错误后).顺便提一下,在启用优化的情况下,gcc会为函数生成无限循环而不是递归,因此永远不会溢出堆栈.使用`-O0`,信号处理程序按预期运行. (3认同)
  • 在某些系统上,堆栈溢出可能会产生`SIGSTKFLT`而不是`SIGSEGV`,因此您可能需要将两者都处理为"可移植". (3认同)
  • @Hola Soy Edu,您是否已将带有*指定的初始值设定项列表的`ss'设置为@R ..?否则,问题可能出在`ss.ss_flags`中。[建立新的备用信号栈](http://linux.die.net/man/2/sigaltstack)必须为零。我建议进行编辑以强调这一点。 (2认同)