Throw a "quit" on a KeyboardException in py-framefilter.c
authorTom Tromey <tom@tromey.com>
Tue, 25 Apr 2017 03:47:59 +0000 (21:47 -0600)
committerTom Tromey <tom@tromey.com>
Tue, 27 Mar 2018 03:57:12 +0000 (21:57 -0600)
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-26  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-26  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
gdb/python/py-framefilter.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-framefilter.exp
gdb/testsuite/gdb.python/py-framefilter.py

index 9b29e6e9ff79038b5d05a107409df174e7564fe1..59d7bb8186f760c681c8545855cb14285a0f56e3 100644 (file)
@@ -1,3 +1,9 @@
+2018-03-26  Tom Tromey  <tom@tromey.com>
+
+       * python/py-framefilter.c (throw_quit_or_print_exception): New
+       function.
+       (gdbpy_apply_frame_filter): Use it.
+
 2018-03-26  Tom Tromey  <tom@tromey.com>
 
        PR cli/17716:
index 28d5c37b25bdb4b59e659f8c1ad15b19503d3cc9..0662e689416647dab17bb7f13e91228d9cddaee5 100644 (file)
@@ -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;
index 5537a9178d6480a313e7852f8dc51bba61775371..7ba6dd784f248bb0343085a11d5430795f20818b 100644 (file)
@@ -1,3 +1,9 @@
+2018-03-26  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.
+
 2018-03-26  Tom Tromey  <tom@tromey.com>
 
        PR backtrace/15582:
index cc31dd5893ee588a3598f5137e494dcc9bbeec37..545bf7741eed75d019cbf4cc206227715fb3dbf4 100644 (file)
@@ -213,6 +213,12 @@ 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"
+gdb_test "bt 1" "Quit" "bt 1 with KeyboardInterrupt"
+
+
 # Test with no debuginfo
 
 # We cannot use prepare_for_testing as we have to set the safe-patch
index 0c3a3a91b6c7964d59b47884bee67565213a6e6c..46f752274e3c73b6b7af145d93c144fbeee6933b 100644 (file)
@@ -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():