This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ Exceptions Status


I've written this up to accompany the call today. I have spent the week investigating C++ exceptions; I have come up with these tasks so far. Work - however - is on-going. I wanted to brain-dump the tasks I have created for archive, for peer-review and sanity checking. I've created gnats PRs for all of these tasks with reproducers/test-cases where needed. Comments welcome. If you have encountered any of below, can add to them, or disagree with some statements - please add comments in-line or to the PR. If you believe there are any tasks missing, please add. Thanks

Task #1 (gnats pr 2493): Documentation change regarding the "catch" command. The text needs to be updated regarding current "catch throw or catch catch" support and the confusion between "raised exceptions" and "c++ exceptions" clarified.

Task #2 (gnats pr 2494): "catch throw" and "catch catch" return control of the inferior inside the: "__cxa_throw" and "__cxa_begin_catch" functions respectively. This is not a very good user experience. I would expect "catch throw" and "catch catch" to return control of the inferior in the users' code, just before the throw or catch code executes. The current infrastructure sets a breakpoint on: "__cxa_throw" for "catch throw" and "__cxa_begin_catch" for "catch catch" respectively. I believe that having the inferior stop here is interesting for only a small subset of C++ users. The task here is stopping the inferior at the throw/catch, instead of just after.

A different but related issue concerns me with 2493 and 2494. At the moment, only C++ exceptions are caught via "catch catch" and "catch throw". This is done in a specific way related directly to the level 2 C++ ABI mechanics. But, how is "catch catch" and "catch throw" going to work and expand to other languages like Java and Python? The generic model that exists is just not going to work. Therefore some thought must be given to a language model inside GDB, instead of relying on library or OS specifics to achieve support of features such as stopping on exception raising and handling.

Task #3 (gnats pr 2495): Performing an inferior function call on a function that contains a throw with an out-of-frame exception handler causes GDB to lose control of the inferior. What I believe is happening here is the "__cxa_throw" is invoking "__Unwind_RaiseException" and that is attempting to find a handler during the _UA_SEARCH_PHASE step. Because the handler exists in another frame, and this is an inferior function call with a tinkered stack, the unwinder in not finding a handler. This causes "__Unwind_RaiseException" to return with with the error: _URC_END_OF_STACK and the default handler is called. I believe this default handler just terminates the application. With a handler in the frame, this does not occur as the handler is found in the inferior function frame.

Task #4 (gnats pr 2488): Using "next" command over a C++ "throw" causes GDB to lose control of the inferior. This has taken a large amount of time as it involved having to step through the unwinder code and fully map out the life-cycle of a C++ exception. At the most basic level, the "next" command relies on longjmp breakpoints to reassert control of the inferior after it has been resumed. Unfortunately this will not work with the system unwinder when matching and then transferring control to exceptions handlers. A brief look at the life of a C++ exception is needed to illustrate further.

There are 3 basic states and flow transfer that I understand happen on a throw. A basic work-flow of a throw is:

yourfunction.c:  throw foo
eh_alloc.cc: __cxa_allocate_exception
eh_throw.cc:__cxa_throw calls
unwind.cc:_Unwind_RaiseException

The first phase of the unwind process is: _UA_SEARCH_PHASE. This searches for an exception handler in the current frame (via the C++ personality routine found in eh_personality.cc in this case). If it finds a handler it returns: _URC_HANDLER_FOUND. If it does not it returns: _URC_CONTINUE_UNWIND. The process continues frame-by-frame until if finds an acceptable handler. If it cannot find a handler in any frame, _URC_END_OF_STACK is returned, and the default C++ handler is called.

* If the default C++ handler is called, the next command should return control of the inferior at this call in _Unwind_RaiseException.

unwind.cc:_Unwind_RaiseException calls
unwind.cc: _Unwind_RaiseException_Phase2

At this point the unwinder knows the frame of the exception handler for the exception. The second phase of the unwind process is started with the: _UA_CLEANUP_PHASE. The unwinder calls the personality routine and asks if clean-up is needed in the current frame. In the case of an out-of-frame exception handler and the local-frame has local scope variables, there will be a need to clean-up those variables. In this case a call to uw_install_context is made in the unwinder and control transferred.

* If a local scope variable destructor is called as part of the clean-up phase the next command should return control of the inferior in the local variable destructor.

After clean-up has been completed - or no clean-up is needed - unwinding is resumed and control returned to the exception handler in the frame found in the search phase. In the case of an in-frame exception handler, control is transferred immediately to the in-frame handler - assuming that no local scope variables did not need to be cleaned-up in a local block. This again is done via uw_install_context.

* If there was no clean-up to perform, or the handler is in-frame, control should be returned at the catch statement in the appropriate frame, in the users' code.

The issue that I am currently wrestling with is how specific is this unwind and exception work to C++? Are Java and Python exceptions handled in the same way? And how can we avoid language specific semantics in very general commands like "next"? Can we?

Regards

Phil


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]