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

时间:2011-04-26 03:57:32

标签: c posix signals

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

2 个答案:

答案 0 :(得分: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);
}

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

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

答案 1 :(得分:0)

#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

static void handler(int signo)
{
    int x;
    if(signo == SIGSEGV)
    {
        printf("Waoh, caught signal %s\n",strsignal(signo));
        printf("Top of stack is near %10p", (void*)&x);
    }
    _exit(EXIT_FAILURE);
}

static void overflowStack(int i)
{
    char a[8964];
    printf("(%d) Called overflow function. The top of stack is near %10p\n",i ,&a[0]);
    overflowStack(i+1);
}

int main(int argc, char *argv[])
{


    /*(1)specify that the signal handler will be allocated onto the
    alternate signal stack*/
    stack_t sigstack;
    //malloc return the pointer to the allocated memory on success
    //malloc return NULL on error
    sigstack.ss_sp = malloc(SIGSTKSZ);
    if( sigstack.ss_sp == NULL)
    {
        printf("Err: malloc error\n");
        exit(EXIT_FAILURE);
    }
    sigstack.ss_size = SIGSTKSZ;
    sigstack.ss_flags = 0;

    /*(2)Specify that the signal handler will be allocated on the alternate 
    signal stack */
    if(sigaltstack(&sigstack, NULL) == -1)
    {
        printf("Err: sigaltstack error\n");
        exit(EXIT_FAILURE);
    }
    // sbrk() change the location of the program break, which defines the end of the process's data segment 
    //On success, sbrk() returns the previous program break. 
    printf("Now the alternate signal stack is successfully allocated\n");
    printf("The address of signal stack is : %10p - %10p\n",sigstack.ss_sp,(char*)sbrk(0)-1);

    /*(3)define a struct sigaction to deal with the SIGSEGV*/
    struct sigaction act;
    act.sa_flags = SA_ONSTACK;
    sigemptyset(&act.sa_mask);
    act.sa_handler = handler;
    sigaction(SIGSEGV, &act, NULL);

    overflowStack(1);

}
相关问题