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]

[RFC] Set unwindonsignal to on by default


I wonder if there a world record for the longest description of a one line patch. I'll describe the problem....

For most systems GCC uses the exception handling strategy documented here: http://www.codesourcery.com/public/cxx-abi/

This strategy tries to find an exception handler firstly "in frame"; if none is found, it unwinds the stack until it finds a handler that can handle the exception. If it cannot find an exception handler anywhere in the stack, it calls std::terminate. This checks to see if there is a custom "default handler" and if found, executes that. If it cannot find a custom "default handler", or when a custom handler returns, std::abort is called and the process exits subsequent to being delivered a SIGABRT. That is a gross simplication of the sequence, but that is the basic strategy. In the normal execution of a process, this is sane and correct - if there is no handler for an exception anywhere in the stack, there is little else than can be done. However in the artifically constructed environment of the debugger controlling the inferior, it can become problematic in some situations. Inferior function calls are one of the situations where this becomes problematic.

In GDB inferior function calls are very common. For example:

(gdb) print foo()

Will print the result (return value) of that function. To do that GDB must create an inferior function call that executes the function in a dummy frame. This isolated and dummy frame is problematic as it cannot be unwound (moving up the stack) beyond the dummy frame.

If an exception is generated by foo() when the function is being executed in the inferior function call, and it does not happen to have an in-frame exception handler, the whole inferior is (wrongly) terminated. This is because any out-of-frame exception handler that usually handles exceptions in function foo() and are normally "up" in the stack will not be considered. The inferior is terminated as detailed above, has to be restarted, and brought back to state by the (probably frustrated) user. This is wrong in my opinion. It is perfectly legal to have a function handler out-of-frame, and in normal execution it would be found and handled; but the artificial environment constructed around the frame for the purpose of the inferior function call "fools" the unwinder and terminates the inferior.

There is a flag in GDB named: "unwindonsignal" that is currently set to "off". This flag tells the inferior function call code that *if* a signal is delivered to the inferior during an inferior function call, to unwind the stack to the state before the dummy frame was completed. This restores the state of the inferior as if the inferior function call (for all intents and purposes,) did not happen. This does not fix the exception issue - out-of-frame exception handlers are still not found when a dummy frame is created. But it does fix the worst complications and does not terminate the inferior.

I propose via this patch that we set the flag to "on" as default. It can always be turned off if the user desires it. Defaulting to "on" will improve the C++ user experience. A longer term approach would be as Daniel suggested: a command to restore the frame and clears the signal "after the fact" if the user wants to do so. This is longer term, but equally valid. Another alternative would be to leave "unwindonsignal" off, create an internal breakpoint in std::terminate, and if that "triggers" unwind (perhaps with a flag "unwindonterminate" gating the feature).

Regards

Phil

2008-09-17 Phil Muldoon <pmuldoon@redhat.com>

   * infcall.c: Set unwind_on_signal_p to 1
   by default.



diff --git a/gdb/infcall.c b/gdb/infcall.c
index a6371ea..4dd16e7 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -81,7 +81,7 @@ Coercion of floats to doubles when calling functions is %s.\n"),
 
    The default is to stop in the frame where the signal was received. */
 
-int unwind_on_signal_p = 0;
+int unwind_on_signal_p = 1;
 static void
 show_unwind_on_signal_p (struct ui_file *file, int from_tty,
 			 struct cmd_list_element *c, const char *value)

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