How do I handle and move past a segfault? [duplicate]
Asked Answered
D

1

6

I'm working on a project in C involving linked lists, and I need to segfault a piece of code in order to prove it doesn't work. But my code can't crash.

Here's my handler so far:

typedef void sigfunc(int);
sigfunc *signal(int, sigfunc*);
void Handler(int sig)
{
    if (sig == SIGSEGV)
    printf("received SegFault\n");
    signal(SIGSEGV, &Handler);
}

It needs to survive the segfault. So far, all i get is an infinite loop of "recieved SegFault". Thanks in advance!

Demantoid answered 26/2, 2014 at 20:18 Comment(4)
Calling printf() in a signal handler is not safe. #8493595Eogene
For your specific use case, you might be better off checking each pointer for validity (this might require ensuring that all invalid pointers are null), and detecting the segfault before it happens.Beaulahbeaulieu
This question seems to be accumulating downvotes... I don't agree that it's a particularly bad question; the only major problem with it is that the correct answer is "you can't" (and the asker can't be expected to know that in advance).Beaulahbeaulieu
The question is "a bomb has gone off; my building is now structurally unstable and about to collapse. There may be arbitrarily more bombs in the structure that any action may trigger. How do I ignore all that and keep on living there normally forever?" You don't; you get out of that situation as quickly as you can. The process is going down; let it go down.Alleyne
T
8

Generally speaking, once you've hit a SEGFAULT your process is done.

In specialized terms, it might be possible to recover, but doing so without being acutely aware of what you're doing is a recipe for repeated failures, memory leaks, invalid pointers, and a nightmare of other problems.

That being said, unless you can restart your process (which avoids all of the above), you can try to recover using setjmp() and longjmp(). For example:

#include <setjmp.h>
jmp_buf restore_point;
void Handler(int sig)
{
    if (sig == SIGSEGV)
    {
        printf("received SegFault\n");
        signal(SIGSEGV, &Handler);
        longjmp(restore_point, SIGSEGV);
    }
}


void test()
{
    int fault_code = setjmp(restore_point);
    if (fault_code == 0)
    {
        // do something that might cause a segfault
    }
    else
    {
        printf("recovered from a fault; code = %d\n", fault_code);
    }
}

In addition to the other problems I've listed, another is that the restore point (jump buffer) you set is only valid until the scope that calls setjmp() is terminated.... you must not jump back into a terminated scope!

In essence, longjmp() is a far-reaching goto, but more like a gobackto since it goes back to the point the jump buffer was initialized. It got initialized by the setjmp() function in a manner than ensures setjmp() will return 0 when it's called linearly, and it will return non-zero when it's reached by being longjmp'd into. In that case, it returns whatever longjmp()s second parameter is (unless that parameter == 0, in which case it returns non-zero still).

Seriously, I've given you enough information to make you dangerous, but don't take my cautions lightly... it's far easier to compound your problems with this approach than it is to fix them, unless you've taken great care and limited your use of this tool.

Tilden answered 26/2, 2014 at 20:27 Comment(1)
I'm aware that generally speaking this is a horrible idea. It's for a project in a class. I'd never try to pull this crap in the real world. I just need to segfault it AND survive in order to return all the right stuff for the program. Thanks!Demantoid

© 2022 - 2024 — McMap. All rights reserved.