Simplify exception handling in py-framefilter.c

This patch changes py-framefilter.c as suggested by Pedro in:
https://sourceware.org/ml/gdb-patches/2017-06/msg00748.html

In particular, gdb exceptions are now caught at the outermost layer,
rather than in each particular function.  This simplifies much of the
code.

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

	* python/py-framefilter.c (py_print_type): Don't catch
	exceptions.  Return void.
	(py_print_value): Likewise.
	(py_print_single_arg): Likewise.
	(enumerate_args): Don't catch exceptions.
	(py_print_args): Likewise.
	(py_print_frame): Likewise.
	(gdbpy_apply_frame_filter): Catch exceptions here.
This commit is contained in:
Tom Tromey 2018-03-23 10:32:26 -06:00
parent 9507b29c0a
commit 76c939acfd
2 changed files with 174 additions and 401 deletions

View File

@ -1,3 +1,14 @@
2018-03-26 Tom Tromey <tom@tromey.com>
* python/py-framefilter.c (py_print_type): Don't catch
exceptions. Return void.
(py_print_value): Likewise.
(py_print_single_arg): Likewise.
(enumerate_args): Don't catch exceptions.
(py_print_args): Likewise.
(py_print_frame): Likewise.
(gdbpy_apply_frame_filter): Catch exceptions here.
2018-03-26 Tom Tromey <tom@tromey.com> 2018-03-26 Tom Tromey <tom@tromey.com>
* stack.c (_initialize_stack): Remove trailing newlines from help * stack.c (_initialize_stack): Remove trailing newlines from help

View File

@ -199,30 +199,16 @@ mi_should_print (struct symbol *sym, enum mi_print_types type)
/* Helper function which outputs a type name extracted from VAL to a /* Helper function which outputs a type name extracted from VAL to a
"type" field in the output stream OUT. OUT is the ui-out structure "type" field in the output stream OUT. OUT is the ui-out structure
the type name will be output too, and VAL is the value that the the type name will be output too, and VAL is the value that the
type will be extracted from. Returns EXT_LANG_BT_ERROR on error, with type will be extracted from. */
any GDB exceptions converted to a Python exception, or EXT_LANG_BT_OK on
success. */
static enum ext_lang_bt_status static void
py_print_type (struct ui_out *out, struct value *val) py_print_type (struct ui_out *out, struct value *val)
{ {
TRY
{
check_typedef (value_type (val)); check_typedef (value_type (val));
string_file stb; string_file stb;
type_print (value_type (val), "", &stb, -1); type_print (value_type (val), "", &stb, -1);
out->field_stream ("type", stb); out->field_stream ("type", stb);
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
return EXT_LANG_BT_OK;
} }
/* Helper function which outputs a value to an output field in a /* Helper function which outputs a value to an output field in a
@ -230,11 +216,9 @@ py_print_type (struct ui_out *out, struct value *val)
VAL is the value that will be printed, OPTS contains the value VAL is the value that will be printed, OPTS contains the value
printing options, ARGS_TYPE is an enumerator describing the printing options, ARGS_TYPE is an enumerator describing the
argument format, and LANGUAGE is the language_defn that the value argument format, and LANGUAGE is the language_defn that the value
will be printed with. Returns EXT_LANG_BT_ERROR on error, with any GDB will be printed with. */
exceptions converted to a Python exception, or EXT_LANG_BT_OK on
success. */
static enum ext_lang_bt_status static void
py_print_value (struct ui_out *out, struct value *val, py_print_value (struct ui_out *out, struct value *val,
const struct value_print_options *opts, const struct value_print_options *opts,
int indent, int indent,
@ -249,18 +233,7 @@ py_print_value (struct ui_out *out, struct value *val,
if (args_type == MI_PRINT_SIMPLE_VALUES if (args_type == MI_PRINT_SIMPLE_VALUES
|| args_type == MI_PRINT_ALL_VALUES) || args_type == MI_PRINT_ALL_VALUES)
{ {
struct type *type = NULL; struct type *type = check_typedef (value_type (val));
TRY
{
type = check_typedef (value_type (val));
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
if (args_type == MI_PRINT_ALL_VALUES) if (args_type == MI_PRINT_ALL_VALUES)
should_print = 1; should_print = 1;
@ -274,23 +247,12 @@ py_print_value (struct ui_out *out, struct value *val,
should_print = 1; should_print = 1;
if (should_print) if (should_print)
{
TRY
{ {
string_file stb; string_file stb;
common_val_print (val, &stb, indent, opts, language); common_val_print (val, &stb, indent, opts, language);
out->field_stream ("value", stb); out->field_stream ("value", stb);
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
return EXT_LANG_BT_OK;
} }
/* Helper function to call a Python method and extract an iterator /* Helper function to call a Python method and extract an iterator
@ -338,10 +300,9 @@ get_py_iter_from_func (PyObject *filter, const char *func)
ARGS_TYPE is an enumerator describing the argument format, ARGS_TYPE is an enumerator describing the argument format,
PRINT_ARGS_FIELD is a flag which indicates if we output "ARGS=1" PRINT_ARGS_FIELD is a flag which indicates if we output "ARGS=1"
in MI output in commands where both arguments and locals are in MI output in commands where both arguments and locals are
printed. Returns EXT_LANG_BT_ERROR on error, with any GDB exceptions printed. */
converted to a Python exception, or EXT_LANG_BT_OK on success. */
static enum ext_lang_bt_status static void
py_print_single_arg (struct ui_out *out, py_print_single_arg (struct ui_out *out,
const char *sym_name, const char *sym_name,
struct frame_arg *fa, struct frame_arg *fa,
@ -352,20 +313,17 @@ py_print_single_arg (struct ui_out *out,
const struct language_defn *language) const struct language_defn *language)
{ {
struct value *val; struct value *val;
enum ext_lang_bt_status retval = EXT_LANG_BT_OK;
if (fa != NULL) if (fa != NULL)
{ {
if (fa->val == NULL && fa->error == NULL) if (fa->val == NULL && fa->error == NULL)
return EXT_LANG_BT_OK; return;
language = language_def (SYMBOL_LANGUAGE (fa->sym)); language = language_def (SYMBOL_LANGUAGE (fa->sym));
val = fa->val; val = fa->val;
} }
else else
val = fv; val = fv;
TRY
{
gdb::optional<ui_out_emit_tuple> maybe_tuple; gdb::optional<ui_out_emit_tuple> maybe_tuple;
/* MI has varying rules for tuples, but generally if there is only /* MI has varying rules for tuples, but generally if there is only
@ -420,13 +378,8 @@ py_print_single_arg (struct ui_out *out,
weird, but this is how MI choose to format the various output weird, but this is how MI choose to format the various output
types. */ types. */
if (args_type == MI_PRINT_SIMPLE_VALUES && val != NULL) if (args_type == MI_PRINT_SIMPLE_VALUES && val != NULL)
{ py_print_type (out, val);
if (py_print_type (out, val) == EXT_LANG_BT_ERROR)
retval = EXT_LANG_BT_ERROR;
}
if (retval != EXT_LANG_BT_ERROR)
{
if (val != NULL) if (val != NULL)
annotate_arg_value (value_type (val)); annotate_arg_value (value_type (val));
@ -447,21 +400,10 @@ py_print_single_arg (struct ui_out *out,
_("<error reading variable: %s>"), _("<error reading variable: %s>"),
fa->error); fa->error);
} }
else if (py_print_value (out, val, opts, 0, args_type, language) else
== EXT_LANG_BT_ERROR) py_print_value (out, val, opts, 0, args_type, language);
retval = EXT_LANG_BT_ERROR;
} }
} }
}
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
retval = EXT_LANG_BT_ERROR;
}
END_CATCH
return retval;
} }
/* Helper function to loop over frame arguments provided by the /* Helper function to loop over frame arguments provided by the
@ -494,16 +436,7 @@ enumerate_args (PyObject *iter,
opts.deref_ref = 1; opts.deref_ref = 1;
TRY
{
annotate_frame_args (); annotate_frame_args ();
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
/* Collect the first argument outside of the loop, so output of /* Collect the first argument outside of the loop, so output of
commas in the argument output is correct. At the end of the commas in the argument output is correct. At the end of the
@ -550,16 +483,7 @@ enumerate_args (PyObject *iter,
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
} }
TRY
{
read_frame_arg (sym, frame, &arg, &entryarg); read_frame_arg (sym, frame, &arg, &entryarg);
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
gdb::unique_xmalloc_ptr<char> arg_holder (arg.error); gdb::unique_xmalloc_ptr<char> arg_holder (arg.error);
gdb::unique_xmalloc_ptr<char> entry_holder (entryarg.error); gdb::unique_xmalloc_ptr<char> entry_holder (entryarg.error);
@ -570,47 +494,32 @@ enumerate_args (PyObject *iter,
if (arg.entry_kind != print_entry_values_only) if (arg.entry_kind != print_entry_values_only)
{ {
if (py_print_single_arg (out, NULL, &arg, py_print_single_arg (out, NULL, &arg,
NULL, &opts, NULL, &opts,
args_type, args_type,
print_args_field, print_args_field,
NULL) == EXT_LANG_BT_ERROR) NULL);
return EXT_LANG_BT_ERROR;
} }
if (entryarg.entry_kind != print_entry_values_no) if (entryarg.entry_kind != print_entry_values_no)
{ {
if (arg.entry_kind != print_entry_values_only) if (arg.entry_kind != print_entry_values_only)
{
TRY
{ {
out->text (", "); out->text (", ");
out->wrap_hint (" "); out->wrap_hint (" ");
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
if (py_print_single_arg (out, NULL, &entryarg, NULL, &opts, py_print_single_arg (out, NULL, &entryarg, NULL, &opts,
args_type, print_args_field, NULL) args_type, print_args_field, NULL);
== EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
} }
} }
else else
{ {
/* If the object has provided a value, we just print that. */ /* If the object has provided a value, we just print that. */
if (val != NULL) if (val != NULL)
{ py_print_single_arg (out, sym_name.get (), NULL, val, &opts,
if (py_print_single_arg (out, sym_name.get (), NULL, val, &opts,
args_type, print_args_field, args_type, print_args_field,
language) == EXT_LANG_BT_ERROR) language);
return EXT_LANG_BT_ERROR;
}
} }
/* Collect the next item from the iterator. If /* Collect the next item from the iterator. If
@ -618,32 +527,12 @@ enumerate_args (PyObject *iter,
comma. */ comma. */
item.reset (PyIter_Next (iter)); item.reset (PyIter_Next (iter));
if (item != NULL) if (item != NULL)
{
TRY
{
out->text (", "); out->text (", ");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
else if (PyErr_Occurred ()) else if (PyErr_Occurred ())
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
TRY
{
annotate_arg_end (); annotate_arg_end ();
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
return EXT_LANG_BT_OK; return EXT_LANG_BT_OK;
} }
@ -703,18 +592,7 @@ enumerate_locals (PyObject *iter,
/* If the object did not provide a value, read it. */ /* If the object did not provide a value, read it. */
if (val == NULL) if (val == NULL)
{
TRY
{
val = read_var_value (sym, sym_block, frame); val = read_var_value (sym, sym_block, frame);
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
/* With PRINT_NO_VALUES, MI does not emit a tuple normally as /* With PRINT_NO_VALUES, MI does not emit a tuple normally as
each output contains only one field. The exception is each output contains only one field. The exception is
@ -724,8 +602,6 @@ enumerate_locals (PyObject *iter,
if (print_args_field || args_type != NO_VALUES) if (print_args_field || args_type != NO_VALUES)
tuple.emplace (out, nullptr); tuple.emplace (out, nullptr);
} }
TRY
{
if (! out->is_mi_like_p ()) if (! out->is_mi_like_p ())
{ {
/* If the output is not MI we indent locals. */ /* If the output is not MI we indent locals. */
@ -736,19 +612,9 @@ enumerate_locals (PyObject *iter,
if (! out->is_mi_like_p ()) if (! out->is_mi_like_p ())
out->text (" = "); out->text (" = ");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
if (args_type == MI_PRINT_SIMPLE_VALUES) if (args_type == MI_PRINT_SIMPLE_VALUES)
{ py_print_type (out, val);
if (py_print_type (out, val) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
}
/* CLI always prints values for locals. MI uses the /* CLI always prints values for locals. MI uses the
simple/no/all system. */ simple/no/all system. */
@ -756,31 +622,18 @@ enumerate_locals (PyObject *iter,
{ {
int val_indent = (indent + 1) * 4; int val_indent = (indent + 1) * 4;
if (py_print_value (out, val, &opts, val_indent, args_type, py_print_value (out, val, &opts, val_indent, args_type,
language) == EXT_LANG_BT_ERROR) language);
return EXT_LANG_BT_ERROR;
} }
else else
{ {
if (args_type != NO_VALUES) if (args_type != NO_VALUES)
{ py_print_value (out, val, &opts, 0, args_type,
if (py_print_value (out, val, &opts, 0, args_type, language);
language) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
}
} }
TRY
{
out->text ("\n"); out->text ("\n");
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
if (!PyErr_Occurred ()) if (!PyErr_Occurred ())
return EXT_LANG_BT_OK; return EXT_LANG_BT_OK;
@ -862,36 +715,18 @@ py_print_args (PyObject *filter,
ui_out_emit_list list_emitter (out, "args"); ui_out_emit_list list_emitter (out, "args");
TRY
{
out->wrap_hint (" "); out->wrap_hint (" ");
annotate_frame_args (); annotate_frame_args ();
if (! out->is_mi_like_p ()) if (! out->is_mi_like_p ())
out->text (" ("); out->text (" (");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
if (args_iter != Py_None if (args_iter != Py_None
&& (enumerate_args (args_iter.get (), out, args_type, 0, frame) && (enumerate_args (args_iter.get (), out, args_type, 0, frame)
== EXT_LANG_BT_ERROR)) == EXT_LANG_BT_ERROR))
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
TRY
{
if (! out->is_mi_like_p ()) if (! out->is_mi_like_p ())
out->text (")"); out->text (")");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
return EXT_LANG_BT_OK; return EXT_LANG_BT_OK;
} }
@ -944,16 +779,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
if (frame == NULL) if (frame == NULL)
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
TRY
{
gdbarch = get_frame_arch (frame); gdbarch = get_frame_arch (frame);
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
/* stack-list-variables. */ /* stack-list-variables. */
if (print_locals && print_args && ! print_frame_info) if (print_locals && print_args && ! print_frame_info)
@ -976,18 +802,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
/* Elided frames are also printed with this function (recursively) /* Elided frames are also printed with this function (recursively)
and are printed with indention. */ and are printed with indention. */
if (indent > 0) if (indent > 0)
{
TRY
{
out->spaces (indent * 4); out->spaces (indent * 4);
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
/* The address is required for frame annotations, and also for /* The address is required for frame annotations, and also for
address printing. */ address printing. */
@ -1017,8 +832,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
slot = (struct frame_info **) htab_find_slot (levels_printed, slot = (struct frame_info **) htab_find_slot (levels_printed,
frame, INSERT); frame, INSERT);
TRY
{
level = frame_relative_level (frame); level = frame_relative_level (frame);
/* Check if this frame has already been printed (there are cases /* Check if this frame has already been printed (there are cases
@ -1037,34 +851,18 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
level); level);
} }
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
if (print_frame_info) if (print_frame_info)
{ {
/* Print address to the address field. If an address is not provided, /* Print address to the address field. If an address is not provided,
print nothing. */ print nothing. */
if (opts.addressprint && has_addr) if (opts.addressprint && has_addr)
{
TRY
{ {
annotate_frame_address (); annotate_frame_address ();
out->field_core_addr ("addr", gdbarch, address); out->field_core_addr ("addr", gdbarch, address);
annotate_frame_address_end (); annotate_frame_address_end ();
out->text (" in "); out->text (" in ");
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
/* Print frame function name. */ /* Print frame function name. */
if (PyObject_HasAttrString (filter, "function")) if (PyObject_HasAttrString (filter, "function"))
@ -1104,21 +902,12 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
} }
TRY
{
annotate_frame_function_name (); annotate_frame_function_name ();
if (function == NULL) if (function == NULL)
out->field_skip ("func"); out->field_skip ("func");
else else
out->field_string ("func", function); out->field_string ("func", function);
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
} }
@ -1132,17 +921,8 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
/* File name/source/line number information. */ /* File name/source/line number information. */
if (print_frame_info) if (print_frame_info)
{
TRY
{ {
annotate_frame_source_begin (); annotate_frame_source_begin ();
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
if (PyObject_HasAttrString (filter, "filename")) if (PyObject_HasAttrString (filter, "filename"))
{ {
@ -1159,21 +939,12 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
if (filename == NULL) if (filename == NULL)
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
TRY
{
out->wrap_hint (" "); out->wrap_hint (" ");
out->text (" at "); out->text (" at ");
annotate_frame_source_file (); annotate_frame_source_file ();
out->field_string ("file", filename.get ()); out->field_string ("file", filename.get ());
annotate_frame_source_file_end (); annotate_frame_source_file_end ();
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
} }
if (PyObject_HasAttrString (filter, "line")) if (PyObject_HasAttrString (filter, "line"))
@ -1190,38 +961,20 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
if (PyErr_Occurred ()) if (PyErr_Occurred ())
return EXT_LANG_BT_ERROR; return EXT_LANG_BT_ERROR;
TRY
{
out->text (":"); out->text (":");
annotate_frame_source_line (); annotate_frame_source_line ();
out->field_int ("line", line); out->field_int ("line", line);
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
} }
} }
/* For MI we need to deal with the "children" list population of /* For MI we need to deal with the "children" list population of
elided frames, so if MI output detected do not send newline. */ elided frames, so if MI output detected do not send newline. */
if (! out->is_mi_like_p ()) if (! out->is_mi_like_p ())
{
TRY
{ {
annotate_frame_end (); annotate_frame_end ();
out->text ("\n"); out->text ("\n");
} }
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
if (print_locals) if (print_locals)
{ {
@ -1434,8 +1187,17 @@ gdbpy_apply_frame_filter (const struct extension_language_defn *extlang,
} }
} }
TRY
{
success = py_print_frame (item.get (), flags, args_type, out, 0, success = py_print_frame (item.get (), flags, args_type, out, 0,
levels_printed.get ()); levels_printed.get ());
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
success = EXT_LANG_BT_ERROR;
}
END_CATCH
/* Do not exit on error printing a single frame. Print the /* Do not exit on error printing a single frame. Print the
error and continue with other frames. */ error and continue with other frames. */