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:
parent
169bb27bce
commit
5c329e6ab4
7 changed files with 121 additions and 73 deletions
|
@ -591,6 +591,60 @@ int gdbpy_initialize_xmethods (void)
|
|||
int gdbpy_initialize_unwind (void)
|
||||
CPYCHECKER_NEGATIVE_RESULT_SETS_EXCEPTION;
|
||||
|
||||
/* A wrapper for PyErr_Fetch that handles reference counting for the
|
||||
caller. */
|
||||
class gdbpy_err_fetch
|
||||
{
|
||||
public:
|
||||
|
||||
gdbpy_err_fetch ()
|
||||
{
|
||||
PyErr_Fetch (&m_error_type, &m_error_value, &m_error_traceback);
|
||||
}
|
||||
|
||||
~gdbpy_err_fetch ()
|
||||
{
|
||||
Py_XDECREF (m_error_type);
|
||||
Py_XDECREF (m_error_value);
|
||||
Py_XDECREF (m_error_traceback);
|
||||
}
|
||||
|
||||
/* Call PyErr_Restore using the values stashed in this object.
|
||||
After this call, this object is invalid and neither the to_string
|
||||
nor restore methods may be used again. */
|
||||
|
||||
void restore ()
|
||||
{
|
||||
PyErr_Restore (m_error_type, m_error_value, m_error_traceback);
|
||||
m_error_type = nullptr;
|
||||
m_error_value = nullptr;
|
||||
m_error_traceback = nullptr;
|
||||
}
|
||||
|
||||
/* Return the string representation of the exception represented by
|
||||
this object. If the result is NULL a python error occurred, the
|
||||
caller must clear it. */
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> to_string () const;
|
||||
|
||||
/* Return the string representation of the type of the exception
|
||||
represented by this object. If the result is NULL a python error
|
||||
occurred, the caller must clear it. */
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> type_to_string () const;
|
||||
|
||||
/* Return true if the stored type matches TYPE, false otherwise. */
|
||||
|
||||
bool type_matches (PyObject *type) const
|
||||
{
|
||||
return PyErr_GivenExceptionMatches (m_error_type, type);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
PyObject *m_error_type, *m_error_value, *m_error_traceback;
|
||||
};
|
||||
|
||||
/* Called before entering the Python interpreter to install the
|
||||
current language and architecture to be used for Python values.
|
||||
Also set the active extension language for GDB so that SIGINT's
|
||||
|
@ -612,7 +666,10 @@ class gdbpy_enter
|
|||
PyGILState_STATE m_state;
|
||||
struct gdbarch *m_gdbarch;
|
||||
const struct language_defn *m_language;
|
||||
PyObject *m_error_type, *m_error_value, *m_error_traceback;
|
||||
|
||||
/* An optional is used here because we don't want to call
|
||||
PyErr_Fetch too early. */
|
||||
gdb::optional<gdbpy_err_fetch> m_error;
|
||||
};
|
||||
|
||||
/* Like gdbpy_enter, but takes a varobj. This is a subclass just to
|
||||
|
@ -665,8 +722,6 @@ gdb::unique_xmalloc_ptr<char> python_string_to_host_string (PyObject *obj);
|
|||
gdbpy_ref<> host_string_to_python_string (const char *str);
|
||||
int gdbpy_is_string (PyObject *obj);
|
||||
gdb::unique_xmalloc_ptr<char> gdbpy_obj_to_string (PyObject *obj);
|
||||
gdb::unique_xmalloc_ptr<char> gdbpy_exception_to_string (PyObject *ptype,
|
||||
PyObject *pvalue);
|
||||
|
||||
int gdbpy_is_lazy_string (PyObject *result);
|
||||
void gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue