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>
* 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
"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
type will be extracted from. Returns EXT_LANG_BT_ERROR on error, with
any GDB exceptions converted to a Python exception, or EXT_LANG_BT_OK on
success. */
type will be extracted from. */
static enum ext_lang_bt_status
static void
py_print_type (struct ui_out *out, struct value *val)
{
TRY
{
check_typedef (value_type (val));
string_file stb;
type_print (value_type (val), "", &stb, -1);
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
@ -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
printing options, ARGS_TYPE is an enumerator describing the
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
exceptions converted to a Python exception, or EXT_LANG_BT_OK on
success. */
will be printed with. */
static enum ext_lang_bt_status
static void
py_print_value (struct ui_out *out, struct value *val,
const struct value_print_options *opts,
int indent,
@ -249,18 +233,7 @@ py_print_value (struct ui_out *out, struct value *val,
if (args_type == MI_PRINT_SIMPLE_VALUES
|| args_type == MI_PRINT_ALL_VALUES)
{
struct type *type = NULL;
TRY
{
type = check_typedef (value_type (val));
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
struct type *type = check_typedef (value_type (val));
if (args_type == MI_PRINT_ALL_VALUES)
should_print = 1;
@ -274,23 +247,12 @@ py_print_value (struct ui_out *out, struct value *val,
should_print = 1;
if (should_print)
{
TRY
{
string_file stb;
common_val_print (val, &stb, indent, opts, language);
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
@ -338,10 +300,9 @@ get_py_iter_from_func (PyObject *filter, const char *func)
ARGS_TYPE is an enumerator describing the argument format,
PRINT_ARGS_FIELD is a flag which indicates if we output "ARGS=1"
in MI output in commands where both arguments and locals are
printed. Returns EXT_LANG_BT_ERROR on error, with any GDB exceptions
converted to a Python exception, or EXT_LANG_BT_OK on success. */
printed. */
static enum ext_lang_bt_status
static void
py_print_single_arg (struct ui_out *out,
const char *sym_name,
struct frame_arg *fa,
@ -352,20 +313,17 @@ py_print_single_arg (struct ui_out *out,
const struct language_defn *language)
{
struct value *val;
enum ext_lang_bt_status retval = EXT_LANG_BT_OK;
if (fa != NULL)
{
if (fa->val == NULL && fa->error == NULL)
return EXT_LANG_BT_OK;
return;
language = language_def (SYMBOL_LANGUAGE (fa->sym));
val = fa->val;
}
else
val = fv;
TRY
{
gdb::optional<ui_out_emit_tuple> maybe_tuple;
/* 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
types. */
if (args_type == MI_PRINT_SIMPLE_VALUES && val != NULL)
{
if (py_print_type (out, val) == EXT_LANG_BT_ERROR)
retval = EXT_LANG_BT_ERROR;
}
py_print_type (out, val);
if (retval != EXT_LANG_BT_ERROR)
{
if (val != NULL)
annotate_arg_value (value_type (val));
@ -447,21 +400,10 @@ py_print_single_arg (struct ui_out *out,
_("<error reading variable: %s>"),
fa->error);
}
else if (py_print_value (out, val, opts, 0, args_type, language)
== EXT_LANG_BT_ERROR)
retval = EXT_LANG_BT_ERROR;
else
py_print_value (out, val, opts, 0, args_type, language);
}
}
}
}
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
@ -494,16 +436,7 @@ enumerate_args (PyObject *iter,
opts.deref_ref = 1;
TRY
{
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
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;
}
TRY
{
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> entry_holder (entryarg.error);
@ -570,47 +494,32 @@ enumerate_args (PyObject *iter,
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,
args_type,
print_args_field,
NULL) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
NULL);
}
if (entryarg.entry_kind != print_entry_values_no)
{
if (arg.entry_kind != print_entry_values_only)
{
TRY
{
out->text (", ");
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,
args_type, print_args_field, NULL)
== EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
py_print_single_arg (out, NULL, &entryarg, NULL, &opts,
args_type, print_args_field, NULL);
}
}
else
{
/* If the object has provided a value, we just print that. */
if (val != NULL)
{
if (py_print_single_arg (out, sym_name.get (), NULL, val, &opts,
py_print_single_arg (out, sym_name.get (), NULL, val, &opts,
args_type, print_args_field,
language) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
}
language);
}
/* Collect the next item from the iterator. If
@ -618,32 +527,12 @@ enumerate_args (PyObject *iter,
comma. */
item.reset (PyIter_Next (iter));
if (item != NULL)
{
TRY
{
out->text (", ");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
else if (PyErr_Occurred ())
return EXT_LANG_BT_ERROR;
TRY
{
annotate_arg_end ();
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
return EXT_LANG_BT_OK;
}
@ -703,18 +592,7 @@ enumerate_locals (PyObject *iter,
/* If the object did not provide a value, read it. */
if (val == NULL)
{
TRY
{
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
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)
tuple.emplace (out, nullptr);
}
TRY
{
if (! out->is_mi_like_p ())
{
/* If the output is not MI we indent locals. */
@ -736,19 +612,9 @@ enumerate_locals (PyObject *iter,
if (! out->is_mi_like_p ())
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 (py_print_type (out, val) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
}
py_print_type (out, val);
/* CLI always prints values for locals. MI uses the
simple/no/all system. */
@ -756,31 +622,18 @@ enumerate_locals (PyObject *iter,
{
int val_indent = (indent + 1) * 4;
if (py_print_value (out, val, &opts, val_indent, args_type,
language) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
py_print_value (out, val, &opts, val_indent, args_type,
language);
}
else
{
if (args_type != NO_VALUES)
{
if (py_print_value (out, val, &opts, 0, args_type,
language) == EXT_LANG_BT_ERROR)
return EXT_LANG_BT_ERROR;
}
py_print_value (out, val, &opts, 0, args_type,
language);
}
TRY
{
out->text ("\n");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
if (!PyErr_Occurred ())
return EXT_LANG_BT_OK;
@ -862,36 +715,18 @@ py_print_args (PyObject *filter,
ui_out_emit_list list_emitter (out, "args");
TRY
{
out->wrap_hint (" ");
annotate_frame_args ();
if (! out->is_mi_like_p ())
out->text (" (");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
if (args_iter != Py_None
&& (enumerate_args (args_iter.get (), out, args_type, 0, frame)
== EXT_LANG_BT_ERROR))
return EXT_LANG_BT_ERROR;
TRY
{
if (! out->is_mi_like_p ())
out->text (")");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
return EXT_LANG_BT_OK;
}
@ -944,16 +779,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
if (frame == NULL)
return EXT_LANG_BT_ERROR;
TRY
{
gdbarch = get_frame_arch (frame);
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
/* stack-list-variables. */
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)
and are printed with indention. */
if (indent > 0)
{
TRY
{
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
address printing. */
@ -1017,8 +832,7 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
slot = (struct frame_info **) htab_find_slot (levels_printed,
frame, INSERT);
TRY
{
level = frame_relative_level (frame);
/* 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);
}
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
if (print_frame_info)
{
/* Print address to the address field. If an address is not provided,
print nothing. */
if (opts.addressprint && has_addr)
{
TRY
{
annotate_frame_address ();
out->field_core_addr ("addr", gdbarch, address);
annotate_frame_address_end ();
out->text (" in ");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
/* Print frame function name. */
if (PyObject_HasAttrString (filter, "function"))
@ -1104,21 +902,12 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
return EXT_LANG_BT_ERROR;
}
TRY
{
annotate_frame_function_name ();
if (function == NULL)
out->field_skip ("func");
else
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. */
if (print_frame_info)
{
TRY
{
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"))
{
@ -1159,21 +939,12 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
if (filename == NULL)
return EXT_LANG_BT_ERROR;
TRY
{
out->wrap_hint (" ");
out->text (" at ");
annotate_frame_source_file ();
out->field_string ("file", filename.get ());
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"))
@ -1190,38 +961,20 @@ py_print_frame (PyObject *filter, frame_filter_flags flags,
if (PyErr_Occurred ())
return EXT_LANG_BT_ERROR;
TRY
{
out->text (":");
annotate_frame_source_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
elided frames, so if MI output detected do not send newline. */
if (! out->is_mi_like_p ())
{
TRY
{
annotate_frame_end ();
out->text ("\n");
}
CATCH (except, RETURN_MASK_ERROR)
{
gdbpy_convert_exception (except);
return EXT_LANG_BT_ERROR;
}
END_CATCH
}
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,
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
error and continue with other frames. */