Friday, June 09, 2006

How do I exit thee? Let me count the ways

[reading: Tom Holt, "Alexander at the World's End"]

Today I've been trying to sort out the interactions between the various different mechanisms for generating and catching errors in Windows. With the help of a noddy test program, I ended up with:

Type No handler atexit signal catch (...) set_terminate __except (EXCEPTION_EXECUTE_HANDLER) __except (EXCEPTION_CONTINUE_EXECUTION) SetUnhandledExceptionFilter
exit(0) No message Hit
abort() Visual C++ Runtime Error dialog Hit (SIGABRT)
c=*(char*)0 'Encountered a problem and needs to close' dialog Hit (SIGSEGV) Hit Hit Hit, generates infinite loop Hit
i=1/0 'Encountered a problem and needs to close' dialog Hit Hit Hit, generates infinite loop Hit
raise() No message Hit, execution continues from the raise
throw Visual C++ Runtime Error dialog Hit Hit Hit
RaiseException(0xE0000001,EXCEPTION_NONCONTINUABLE, 0, NULL) 'Encountered a problem and needs to close' dialog Hit Hit Hit Hit
RaiseException(0xE0000001, 0, 0, NULL) 'Encountered a problem and needs to close' dialog Hit Hit Hit, execution continues from the RaiseException Hit

Other key points to note:

  • All catchers only see errors from the same thread, with the exception of the SEH unhandled exception filter set by SetUnhandledExceptionFilter().
  • For (say) a null dereference, the order that various handlers get to see things is:
    • Vectored Exception Handler (VEH)
    • C++ exception handler or Structured Exception Handler (SEH), whichever has the narrower enclosing scope
    • SIGSEGV signal handler /* FALLTHRU */
    • SEH unhandled exception filter installed by SetUnhandledExceptionFilter
    • C++ unhandled exception handler installed by set_terminate
  • I've no idea why a null dereference does appear as a C++ exception in a catch (...) block, but doesn't hit the unhandled-C++-exception-handler installed by set_terminate.

No comments: