Hi i am attempting to test a code to see if it is designed to handle memory issues.
Unfortunately I have to do this through c-unit which doesn't handle segmentation faults very well (just crashes out)
So my question is can i add a signal handler to the code i am testing to allow it to exit out of the offending function instead of exiting the entire program?
Essentially can I modify the following handler to exit from function and return to my cunit framework ?
void sighandler(int signo, siginfo_t *si, ucontext_t* context)
{
printf("Handler executed for signal %d\n", signo);
exit(0); /* can i replace this with exit from function? */
}
It can be done with a signal handler plus setjmp
/longjmp
.
I'm not sure how reliable this solution is. It works when I tested it, but may include undefined behavior, so don't rely on it.
It's also important to note that buggy code can do worse things than a segmentation fault. It can, for example, corrupt memory, so your test code, or other tested code, will fail.
The code below is largely based on this answer.
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
static void good_func(void)
{
int q, *p = &q;
printf("%s running\n", __FUNCTION__);
*p = 3;
}
static void bad_func(void)
{
int *p = NULL;
printf("%s running\n", __FUNCTION__);
*p = 3;
}
static jmp_buf context;
static void sig_handler(int signo)
{
longjmp(context, 1);
}
static void catch_segv(int catch)
{
struct sigaction sa;
if (catch) {
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = sig_handler;
sa.sa_flags = SA_RESTART;
sigaction(SIGSEGV, &sa, NULL);
} else {
sigemptyset(&sa);
sigaddset(&sa, SIGSEGV);
sigprocmask(SIG_UNBLOCK, &sa, NULL);
}
}
typedef void (*func_t)(void);
static int safe_run(func_t func)
{
catch_segv(1);
if (setjmp(context)) {
catch_segv(0);
return 0;
}
func();
catch_segv(0);
return 1;
}
int main()
{
printf("good_func is %s\n", safe_run(good_func) ? "good" : "bad");
printf("bad_func is %s\n", safe_run(bad_func) ? "good" : "bad");
return 0;
}