From 5c329e6ab4c7bba9b83155571b150756210001df Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 27 Dec 2018 11:32:01 -0700 Subject: 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 * 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) : Remove. : 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. --- gdb/python/python-internal.h | 61 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 3 deletions(-) (limited to 'gdb/python/python-internal.h') diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 51919b7..b5d9840 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -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 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 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 m_error; }; /* Like gdbpy_enter, but takes a varobj. This is a subclass just to @@ -665,8 +722,6 @@ gdb::unique_xmalloc_ptr 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 gdbpy_obj_to_string (PyObject *obj); -gdb::unique_xmalloc_ptr 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, -- cgit v1.1