This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB 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]

[RFA v3 07/13] Throw a "quit" on a KeyboardException in py-framefilter.c


If a C-c comes while the Python code for a frame filter is running, it
will be turned into a Python KeyboardException.  It seems good for
this to be treated like a GDB quit, so this patch changes
py-framefilter.c to notice this situation and call throw_quit in this
case.

gdb/ChangeLog
2018-03-23  Tom Tromey  <tom@tromey.com>

	* python/py-framefilter.c (throw_quit_or_print_exception): New
	function.
	(gdbpy_apply_frame_filter): Use it.

gdb/testsuite/ChangeLog
2018-03-23  Tom Tromey  <tom@tromey.com>

	* gdb.python/py-framefilter.exp: Add test for KeyboardInterrupt.
	* gdb.python/py-framefilter.py (name_error): New global.
	(ErrorInName.function): Use name_error.
---
 gdb/ChangeLog                               |  6 ++++++
 gdb/python/py-framefilter.c                 | 21 ++++++++++++++++++---
 gdb/testsuite/ChangeLog                     |  6 ++++++
 gdb/testsuite/gdb.python/py-framefilter.exp | 10 ++++++++++
 gdb/testsuite/gdb.python/py-framefilter.py  |  6 +++++-
 5 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index 28d5c37b25..0662e68941 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -1305,6 +1305,21 @@ bootstrap_python_frame_filters (struct frame_info *frame,
     return iterable.release ();
 }
 
+/* A helper function that will either print an exception or, if it is
+   a KeyboardException, throw a quit.  This can only be called when
+   the Python exception is set.  */
+
+static void
+throw_quit_or_print_exception ()
+{
+  if (PyErr_ExceptionMatches (PyExc_KeyboardInterrupt))
+    {
+      PyErr_Clear ();
+      throw_quit ("Quit");
+    }
+  gdbpy_print_stack ();
+}
+
 /*  This is the only publicly exported function in this file.  FRAME
     is the source frame to start frame-filter invocation.  FLAGS is an
     integer holding the flags for printing.  The following elements of
@@ -1375,7 +1390,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
 	 initialization error.  This return code will trigger a
 	 default backtrace.  */
 
-      gdbpy_print_stack ();
+      throw_quit_or_print_exception ();
       return EXT_LANG_BT_NO_FILTERS;
     }
 
@@ -1398,7 +1413,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
 	{
 	  if (PyErr_Occurred ())
 	    {
-	      gdbpy_print_stack ();
+	      throw_quit_or_print_exception ();
 	      return EXT_LANG_BT_ERROR;
 	    }
 	  break;
@@ -1423,7 +1438,7 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
       /* Do not exit on error printing a single frame.  Print the
 	 error and continue with other frames.  */
       if (success == EXT_LANG_BT_ERROR)
-	gdbpy_print_stack ();
+	throw_quit_or_print_exception ();
     }
 
   return success;
diff --git a/gdb/testsuite/gdb.python/py-framefilter.exp b/gdb/testsuite/gdb.python/py-framefilter.exp
index cc31dd5893..e28cc3bd4c 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.exp
+++ b/gdb/testsuite/gdb.python/py-framefilter.exp
@@ -213,6 +213,16 @@ gdb_test_multiple "bt 1" $test {
     }
 }
 
+# Now verify that we can see a quit.
+gdb_test_no_output "python name_error = KeyboardInterrupt" \
+    "Change ErrorFilter to throw KeyboardInterrupt"
+set test "bt 1 with KeyboardInterrupt"
+gdb_test_multiple "bt 1" $test {
+    -re "Quit" {
+	pass $test
+    }
+}
+
 # Test with no debuginfo
 
 # We cannot use prepare_for_testing as we have to set the safe-patch
diff --git a/gdb/testsuite/gdb.python/py-framefilter.py b/gdb/testsuite/gdb.python/py-framefilter.py
index 0c3a3a91b6..46f752274e 100644
--- a/gdb/testsuite/gdb.python/py-framefilter.py
+++ b/gdb/testsuite/gdb.python/py-framefilter.py
@@ -134,13 +134,17 @@ class FrameElider ():
     def filter (self, frame_iter):
         return ElidingIterator (frame_iter)
 
+# This is here so the test can change the kind of error that is
+# thrown.
+name_error = RuntimeError
+
 # A simple decorator that gives an error when computing the function.
 class ErrorInName(FrameDecorator):
     def __init__(self, frame):
         FrameDecorator.__init__(self, frame)
 
     def function(self):
-        raise RuntimeError('whoops')
+        raise name_error('whoops')
 
 # A filter that supplies buggy frames.  Disabled by default.
 class ErrorFilter():
-- 
2.13.6


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