I use the following code to print call stack when catching a signal. But it seems that it doesn't work for stack overflow errors. After some experiments, I find this problem may be caused by the call of backtrace
. How can I fix it?
#include <stdlib.h>
#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
void signal_handler(int sig)
{
printf("signal: %d\n", sig);
void* dump_array[256];
int num = backtrace(dump_array, 256);
if (num)
{
printf("backtrace rank = %d\n", num);
char** symbols = backtrace_symbols(dump_array, num);
if (symbols)
{
for (int i = 0; i < num; i++)
printf("%s\n", symbols[i]);
free(symbols);
}
}
exit(-1);
}
void func()
{
func();
}
int main(void)
{
stack_t ss = {};
ss.ss_size = SIGSTKSZ;
if (!(ss.ss_sp = malloc(SIGSTKSZ)))
{
perror("malloc");
exit(-1);
}
if (sigaltstack(&ss, NULL) == -1)
{
perror("sigaltstack");
exit(-1);
}
struct sigaction act = {};
act.sa_handler = signal_handler;
act.sa_flags = SA_ONSTACK;
sigfillset(&act.sa_mask);
if (sigaction(SIGSEGV, &act, NULL) == -1)
perror("sigaction");
*(int*)123 = 456; // works
//func(); // doesn't work
return 0;
}
A usual solution to handling stack-overflow caught by a handler is to use very compiler specific code to do backtracking in a loop . In other words, no function calls including printf("signal: %d\\n", sig);
.
A precaution limits the amount of back-tracing.
A part of signal_handler()
it to handle things differently it a re-entrant signal_handler()
is detected. Perhaps use a static int first_time
flag.
void signal_handler(int sig) {
static int first_time = 0;
if (first_time == 0) {
first_time++;
for (int i = 0; i<max; i++) {
... // gather back trace data
}
}
... // save exit into some place
exit -1;
}
In general, the answer is very compiler dependent.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.