public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
* archer-pmuldoon-exception-rewind quick demo script
@ 2009-01-13 15:23 Phil Muldoon
  0 siblings, 0 replies; only message in thread
From: Phil Muldoon @ 2009-01-13 15:23 UTC (permalink / raw)
  To: Project Archer

Someone asked us to write up demo instructions for our own merged 
branches at the last meeting. Here are mine with a bit of a narrative 
for the features addressed in the 
origin/archer-pmuldoon-exception-rewind branch.

* Build and set-up:

Check out the demo branch.  Configure and build it. I built  my GDB 
out-of-tree, so for the purposes of this demo the base binary directory 
is: "demo_obj".

When the GDB build is done, build the test inferior. It is already in 
the source tree. Here is how I built it:

[pmuldoon@localhost demo_obj]$ g++ -g3 -O0 
../archer/gdb/testsuite/gdb.cp/gdb2495.cc -o gdb2495

And start the freshly built GDB with the test inferior.

[pmuldoon@localhost demo_obj]$ ./gdb/gdb gdb2495

* Old behaviour:

To demonstrate the old non-patched behaviour first turn off the "unwind 
on unhandled exception" flag.

(gdb) set unwind-on-terminating-exception off

Next break at main, and then run:

(gdb) b main
(gdb) r

Breakpoint 1, main () at ../archer/gdb/testsuite/gdb.cp/gdb2495.cc:76
76      exceptions.raise_signal (-1);

Now if we try to print a function that has a "throw" statement but no 
in-frame handler, things go badly wrong:

(gdb) p exceptions.throw_function()
terminate called after throwing an instance of 'int'
Program received signal SIGABRT, Aborted.
0x000000378c632f05 in raise () from /lib64/libc.so.6
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function 
(SimpleException::throw_function()) will be abandoned.

Let's try to step from where we were before we asked for that function 
to be printed.

(gdb) s
Single stepping until exit from function raise,
which has no line number information.
Program terminated with signal SIGABRT, Aborted.
The program no longer exists.

That's not very nice! All I wanted GDB to do was print the output of the 
function and things went badly wrong.  As it is, the inferior has been 
terminated and our abortive GDB debug session is at and end. If we look 
at the contents of the function, it is perfectly normal and legal:

  void throw_function ()
  {
    throw 1;
  }

It threw an exception, but did not handle it. In the normal flow of  
code this exception is handled in another frame. But in the confines of 
the inferior function call and its dummy-frame, all opportunity to find 
the matching exception-handler has been denied. The unwinder throws up 
its proverbial hands and terminates the process.  But this is not 
"normal". Normally, and in this inferior's example,  this code works 
fine when it is run or stepped to completion. It is just the inferior 
function call creating a bogus environment, that "fools" the unwinder 
that results in its termination.

In my opinion - and probably many others - inferior function calls 
should never result in the termination of the inferior. Legal or not, 
horrible or not, the function call should safeguard the inferior. This 
patch addresses one dimension of that.


* New "patched" behaviour:

In the case above, if the user had set "unwindonsignal" to "on", the bad 
frame would have been "popped" and control restored to the point just 
before the inferior function call. But "unwindonsignal" is set to "off" 
by default. Setting this to "on" by default is not desirable. (This 
thread here references why: 
http://sourceware.org/ml/archer/2008-q3/msg00199.html)

So what this branch achieves is to detect the sequence where an 
unhandled exception is about to terminate the application. This is gated 
by the behaviour of the "unwind-on-terminating-exception" flag, which 
defaults to on. When it detects this behaviour it prevents the 
termination, pops the dummy-frame and restores control to the inferior.

Lets restart the application

(gdb) r
Breakpoint 1, main () at ../archer/gdb/testsuite/gdb.cp/gdb2495.cc:76
76      exceptions.raise_signal (-1);

Set the patched behaviour to "on"

(gdb) set unwind-on-terminating-exception on

And try printing the result from  that function again.

(gdb) p exceptions.throw_function()
Breakpoint 0, 0x0000003793ac3d00 in std::terminate() () from 
/usr/lib64/libstdc++.so.6
The program being debugged entered a std::terminate call which would
have terminated the program being debugged.  GDB has restored the
context to what it was before the call.
To change this behaviour use "set unwind-on-terminating-exception off"
Evaluation of the expression containing the function 
(SimpleException::throw_function()) will be abandoned.

This time we detected that the inferior function call was about to enter 
the std::terminate call, prevented it and popped the frame. So we are 
back at the point before we made the call and back to stepping as normal:

(gdb) s
SimpleException::raise_signal (this=0x6013e0, dummy=-1) at 
../archer/gdb/testsuite/gdb.cp/gdb2495.cc:31
31        if (dummy > 0)
(gdb) s
33      }
(gdb) s
main () at ../archer/gdb/testsuite/gdb.cp/gdb2495.cc:77
77      exceptions.no_throw_function ();


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2009-01-13 15:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-13 15:23 archer-pmuldoon-exception-rewind quick demo script Phil Muldoon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).