how to use “sigaltstack” in signal handler program?

前端 未结 2 1674
北海茫月
北海茫月 2020-12-30 09:46

did anyone who knows how to use the sigaltstack in a real signal handler program,a simple but complete code may be great help to me! thank you in advance!

相关标签:
2条回答
  • 2020-12-30 10:11

    Here is a minimal sample program that uses sigaltstack to catch infinite recursion. If you comment out the sigaltstack call or SA_ONSTACK flag, the signal handler will not be able to run because it has no stack left and the program will just crash.

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

    A more sophisticated use might actually perform siglongjmp to jump out of the signal handler and back to a point where the infinite recursion can be avoided. This is not valid if async-signal-unsafe library calls are being used, or if your data might be left in an unsafe/unrecoverable state, but if you're performing pure arithmetic computations, it may be valid.

    Perhaps a better task for the signal handler would be performing an emergency dump of any valuable/critical data that wasn't already saved to disk. This could be difficult if you can't call async-signal-unsafe functions, but it's usually possible if you put some effort into it.

    0 讨论(0)
  • 2020-12-30 10:11
    #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);
    
    }
    
    0 讨论(0)
提交回复
热议问题