Use a wrapper for PyErr_Fetch

This introduces a new class that wraps PyErr_Fetch and PyErr_Restore,
and then changes all the callers in gdb to use it.  This reduces the
amount of explicit reference counting that is done in the Python code.
I also found and fixed a latent bug in gdbpy_print_stack -- it was not
correctly checking some error conditions, nor clearing the exception
when needed.

gdb/ChangeLog
2019-01-03  Tom Tromey  <tom@tromey.com>

	* python/python.c (gdbpy_enter, ~gdbpy_enter): Update.
	(gdbpy_print_stack): Use gdbpy_err_fetch.
	* python/python-internal.h (class gdbpy_err_fetch): New class.
	(class gdbpy_enter) <m_error_type, m_error_value,
	m_error_traceback>: Remove.
	<m_error>: New member.
	(gdbpy_exception_to_string): Don't declare.
	* python/py-varobj.c (py_varobj_iter_next): Use gdbpy_err_fetch.
	* python/py-value.c (convert_value_from_python): Use
	gdbpy_err_fetch.
	* python/py-utils.c (gdbpy_err_fetch::to_string): Rename from
	gdbpy_exception_to_string.
	(gdbpy_handle_exception): Use gdbpy_err_fetch.
	* python/py-prettyprint.c (print_stack_unless_memory_error): Use
	gdbpy_err_fetch.
This commit is contained in:
Tom Tromey
2018-12-27 11:32:01 -07:00
parent 169bb27bce
commit 5c329e6ab4
7 changed files with 121 additions and 73 deletions

View File

@ -214,7 +214,7 @@ gdbpy_enter::gdbpy_enter (struct gdbarch *gdbarch,
python_language = language;
/* Save it and ensure ! PyErr_Occurred () afterwards. */
PyErr_Fetch (&m_error_type, &m_error_value, &m_error_traceback);
m_error.emplace ();
}
gdbpy_enter::~gdbpy_enter ()
@ -227,7 +227,7 @@ gdbpy_enter::~gdbpy_enter ()
warning (_("internal error: Unhandled Python exception"));
}
PyErr_Restore (m_error_type, m_error_value, m_error_traceback);
m_error->restore ();
PyGILState_Release (m_state);
python_gdbarch = m_gdbarch;
@ -1234,24 +1234,25 @@ gdbpy_print_stack (void)
/* Print "message", just error print message. */
else
{
PyObject *ptype, *pvalue, *ptraceback;
gdbpy_err_fetch fetched_error;
PyErr_Fetch (&ptype, &pvalue, &ptraceback);
/* Fetch the error message contained within ptype, pvalue. */
gdb::unique_xmalloc_ptr<char>
msg (gdbpy_exception_to_string (ptype, pvalue));
gdb::unique_xmalloc_ptr<char> type (gdbpy_obj_to_string (ptype));
gdb::unique_xmalloc_ptr<char> msg = fetched_error.to_string ();
gdb::unique_xmalloc_ptr<char> type;
/* Don't compute TYPE if MSG already indicates that there is an
error. */
if (msg != NULL)
type = fetched_error.type_to_string ();
TRY
{
if (msg == NULL)
if (msg == NULL || type == NULL)
{
/* An error occurred computing the string representation of the
error message. */
fprintf_filtered (gdb_stderr,
_("Error occurred computing Python error" \
"message.\n"));
PyErr_Clear ();
}
else
fprintf_filtered (gdb_stderr, "Python Exception %s %s: \n",
@ -1261,10 +1262,6 @@ gdbpy_print_stack (void)
{
}
END_CATCH
Py_XDECREF (ptype);
Py_XDECREF (pvalue);
Py_XDECREF (ptraceback);
}
}