Skip to content
Advertisement

Why signal handler for SIGSEGV doesn’t catch my C++ throw exception?

I was trying to see if SIGSEGV signal hander could help to deal with unhandled exception of C++, I experiment it:

#include <stdio.h>
#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void handler(int sig) {
  void *array[10];
  size_t size = backtrace(array, 10);
  fprintf(stderr, "Error: signal %d:n", sig);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
  exit(1);
}
int main()
{
  signal(SIGSEGV, handler);
  throw 1;
}

$ g++ -g h.cpp -rdynamic && ./a.out

terminate called after throwing an instance of ‘int’ Aborted (Core dump)

Well, the program doesn’t print crash call stack back trace as I expected. My question is:

As long as it terminates, does it through out any signals like SIGSEGV? Is there a system call or posix api that could catch even C++ exceptions and prints out the call stack?

Thanks!

Advertisement

Answer

You can install a termination handler with std::set_terminate – the installed handler will then be invoked for unhandled exception. There is no strong guarantee, but there is a great chance that the invocation of abort that causes invocation of the termination handler is occurring on the top of the stack that threw the exception and thus you can still collect a backtrace.

Also, you can install a handler for SIGABRT, that will work as well:

#include <execinfo.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

void handler(int sig, siginfo_t*, void*) {
  void *array[10];
  size_t size = backtrace(array, 10);
  fprintf(stderr, "Error: signal %d:n", sig);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
  exit(1);
}

void terminate_handler()
{
}

int main()
{
  struct sigaction new_sigaction, old_sigaction;
  new_sigaction.sa_flags = SA_SIGINFO;
  new_sigaction.sa_sigaction = handler;
  sigaction(SIGABRT, &new_sigaction, &old_sigaction);
  throw 1;
}

I’d personally prefer the termination handler, since in that case you explicitly know the cause. If the SIGABRT handler is invoked you must understand if this is because an unhandled exception invoked abort() or the signal was sent by other means.

Advertisement