Hello.

I want to catch stack overflow exceptions in my program.
I use sigaltstack to set up alternate stack on which SIGSEGV signals should 
processed, and siglongjmp from signal handler to jump to restore point.

But in this case signal handler executes on alternate stack only once.
In next times signal handler executes on main program stack.

There is test program:


#include <sys/types.h>
#include <signal.h>
#include <setjmp.h>

#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>

static sigjmp_buf loop;

static int n = 0; /* SIGSEGV counter */

static void *mainStack;

static void TrapHandler (int sig, siginfo_t *sip, void *scp)
{
        printf("[ segmentation violation\n");
        printf("  TrapHandler stack: %p (", &sig);
        if ((unsigned long int)(mainStack) - (unsigned long int)(&sig) > 1000) {
                printf("not ");
        }
        printf("near main stack) ]\n");

        if (n == 5) {
                exit(100); /* too many segmentation faults */
        } else {
                ++n;
                siglongjmp(loop, 1);
        }
}

static int InstallSigSegV ()
{
        int res;
        struct sigaltstack sigstk;
        struct sigaction sa;

        sigstk.ss_sp = malloc(SIGSTKSZ);
        if (sigstk.ss_sp != NULL) {
                sigstk.ss_size = SIGSTKSZ;
                sigstk.ss_flags = 0;
                res = sigaltstack(&sigstk, 0);
                if (res == 0) {
                        sa.sa_sigaction = &TrapHandler;
                        sigfillset(&sa.sa_mask);
                        sa.sa_flags = SA_SIGINFO | SA_ONSTACK;
                        res = sigaction(SIGSEGV, &sa, NULL);
                        if (res != 0) {
                                assert(res == -1);
                                printf("InstallSigSegV: sigaction(SIGSEGV): 
%s\n", strerror(errno));
                                res = 3;
                        }
                } else {
                        assert(res == -1);
                        printf("InstallSigSegV: sigaltstack(%d B): %s\n", 
SIGSTKSZ, strerror(errno));
                        res = 2;
                }
        } else {
                printf("InstallSigSegV: malloc(%d B) failed\n", SIGSTKSZ);
                res = 1;
        }

        return res;
}

static void StackOverflow ()
{
        volatile char c[10240];
        c[0] = 0;
        StackOverflow();
        c[0] = 1;
}

static void InvalidMemoryAccess ()
{
        int *x = 0;
        *x = 0;
}

static void P ()
{
        if (n % 2 != 0) {
                InvalidMemoryAccess();
        } else {
                StackOverflow();
        }
}

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

        mainStack = &res;
        printf("main stack: %p\n", mainStack);

        res = InstallSigSegV();
        if (res == 0)
        {
                res = sigsetjmp(loop, 1);
                assert((res == 0) || (res == 1));

                printf("start...\n");

                P();

                printf("...all done\n");
        }

        return res;
}


There is output (OpenBSD 5.2 / i386):

$ ./test1
main stack: 0xcfbc1c30
start...
[ segmentation violation
  TrapHandler stack: 0x83ac9f1c (not near main stack) ]
start...
[ segmentation violation
  TrapHandler stack: 0xcfbc1b1c (near main stack) ]
start...
Illegal instruction (core dumped) 


Fedora Core 17 / i386:

$ ./test1
main stack: 0xbf95b84c
start...
[ segmentation violation
  TrapHandler stack: 0x9e7ef00 (not near main stack) ]
start...
[ segmentation violation
  TrapHandler stack: 0x9e7ef00 (not near main stack) ]
start...
[ segmentation violation
  TrapHandler stack: 0x9e7ef00 (not near main stack) ]
start...
[ segmentation violation
  TrapHandler stack: 0x9e7ef00 (not near main stack) ]
start...
[ segmentation violation
  TrapHandler stack: 0x9e7ef00 (not near main stack) ]
start...
[ segmentation violation
  TrapHandler stack: 0x9e7ef00 (not near main stack) ]


This is error in OpenBSD or I should use other method to catch stack overflow 
exceptions?
Thank you in advance for your answers.

Best regards, Alexander.

[demime 1.01d removed an attachment of type application/octet-stream which had 
a name of test1.c]

Reply via email to