Catching unwanted exception at throw site


Not sure if this is quite the right place - but maybe somebody here can point me to the right place.

Problem: C++ code throws exception at a point in time where it should really not be throwing an exception. To catch this, I have a lambda declared noexcept.

What I want to happen: the debugger stops, and points me at the line of code that is executing “throw FooException();”

What actually happens: I end up with the stack looking like
(lldb) bt

  • thread #1, name = ‘soffice.bin’, stop reason = signal SIGABRT
    frame #0: at pthread_kill.c:44:76 frame #1: [inlined] __pthread_kill_internal(signo=6, threadid=) at pthread_kill.c:78:10
    frame #2:`__GI___pthread_kill(threadid=, signo=6) at pthread_kill.c:89:10
    • frame #3: at raise.c:26:13 frame #4: at abort.c:79:7
      frame #5: + 96 frame #6: + 12
      frame #7: + 23 frame #8: libvcllo.so__clang_call_terminate + 14
      frame #9:`SalUserEventList::DispatchUserEvents(bool)::$_0::operator()(this=0x00007fffffff3db0) const at salusereventlist.cxx:119:58

This is intrinsic to how the Itanium C++ ABI works: it unwinds the stack until it reaches a catch. The noexcept function is inserting a catch (catchall) that then branches to std::terminate to prevent exceptions from propagating. By the time you land in the lambda, you have already destroyed the stack and so can’t see where it came from. The best thing to do in a debugger is stick a breakpoint on __cxa_throw and script it to print a backtrace and then continue. This will give you a backtrace everywhere that an exception is thrown and the last place you see one before hitting this terminate will be the right one.

Thanks David for that explanation.

Presumably the Itanium ABI is implemented as part of some runtime? Perhaps it could be tweaked to do something different in debug mode? I would imagine that the stack unwinding is non-destructive, so making the stack appear to be coming from a different point should not be that hard?

This is a pain point for any codebase that uses exceptions - what I am trying to do here is not to fix a specific bug, but to make a class of bugs easier to deal with.

Try setting an exception breakpoint with “breakpoint set -E c++”.