From 4ca59a9f3616ba324952632233acc657fffa8be1 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Mon, 24 Apr 2017 21:47:59 -0600 Subject: 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-26 Tom Tromey * 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 * 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 | 6 ++++++ gdb/testsuite/gdb.python/py-framefilter.py | 6 +++++- 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9b29e6e..59d7bb8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,11 @@ 2018-03-26 Tom Tromey + * python/py-framefilter.c (throw_quit_or_print_exception): New + function. + (gdbpy_apply_frame_filter): Use it. + +2018-03-26 Tom Tromey + PR cli/17716: * python/py-framefilter.c (py_print_type, py_print_value) (enumerate_args, py_print_args, gdbpy_apply_frame_filter): Use diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c index 28d5c37..0662e68 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/ChangeLog b/gdb/testsuite/ChangeLog index 5537a91..7ba6dd7 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2018-03-26 Tom Tromey + * 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 + PR backtrace/15582: * gdb.python/py-framefilter.exp: Add "bt hide" test. diff --git a/gdb/testsuite/gdb.python/py-framefilter.exp b/gdb/testsuite/gdb.python/py-framefilter.exp index cc31dd5..545bf77 100644 --- a/gdb/testsuite/gdb.python/py-framefilter.exp +++ b/gdb/testsuite/gdb.python/py-framefilter.exp @@ -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 diff --git a/gdb/testsuite/gdb.python/py-framefilter.py b/gdb/testsuite/gdb.python/py-framefilter.py index 0c3a3a9..46f7522 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(): -- cgit v1.1