I think the approach you are looking for is to handle a SIGSEGV
signal via sigaction
.
void handler(int, siginfo_t *info, ucontext_t *uap)
{
/* Peek at parameters here... I'm not sure exactly what you want to do. */
}
/* Set up the signal handler... */
struct sigaction sa, old_sa;
memset(&sa, 0 sizeof(sa));
sa.sa_sigaction = handler;
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGSEGV, &sa, &old_sa))
{
/* TODO: handle error */
}
Note however that catching SIGSEGV
on your own process is kind of weird. The process is likely in a bad state that can't be recovered from. The actions you'll be able to do in response to it may be limited, and it's most likely the process being killed is a good thing.
If you want it to be a bit more stable, there is the sigaltstack
call which lets you specify an alternate stack buffer, so that if you've completely hosed your stack you can still handle SIGSEGV
. To use this you need to set SA_ONSTACK
in sa.sa_flags
above.
If you want to respond to SEGV
from the safety of another process (thereby isolating yourself from the poorly behaving segfaulting code and making it so that you won't crash while inspecting it), you can use ptrace
. This interface is complex, has many non-portable parts, and is mainly used to write debuggers. But you can do great things with it, like read and write the process's memory and registers, and alter its execution.