diff options
author | Tom Tromey <tom@tromey.com> | 2018-12-27 11:32:01 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2019-01-03 14:49:18 -0700 |
commit | 5c329e6ab4c7bba9b83155571b150756210001df (patch) | |
tree | 35725c6442fabe48ff6f0b573eb6d4985f215618 /gdb/python/py-utils.c | |
parent | 169bb27bce3dc43b2bb5f6abf7fc21c19de5454a (diff) | |
download | gdb-5c329e6ab4c7bba9b83155571b150756210001df.zip gdb-5c329e6ab4c7bba9b83155571b150756210001df.tar.gz gdb-5c329e6ab4c7bba9b83155571b150756210001df.tar.bz2 |
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.
Diffstat (limited to 'gdb/python/py-utils.c')
-rw-r--r-- | gdb/python/py-utils.c | 58 |
1 files changed, 25 insertions, 33 deletions
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c index 66b2a67..0f838c2 100644 --- a/gdb/python/py-utils.c +++ b/gdb/python/py-utils.c @@ -203,28 +203,33 @@ gdbpy_obj_to_string (PyObject *obj) return NULL; } -/* Return the string representation of the exception represented by - TYPE, VALUE which is assumed to have been obtained with PyErr_Fetch, - i.e., the error indicator is currently clear. - If the result is NULL a python error occurred, the caller must clear it. */ +/* See python-internal.h. */ gdb::unique_xmalloc_ptr<char> -gdbpy_exception_to_string (PyObject *ptype, PyObject *pvalue) +gdbpy_err_fetch::to_string () const { /* There are a few cases to consider. For example: - pvalue is a string when PyErr_SetString is used. - pvalue is not a string when raise "foo" is used, instead it is None - and ptype is "foo". - So the algorithm we use is to print `str (pvalue)' if it's not - None, otherwise we print `str (ptype)'. + value is a string when PyErr_SetString is used. + value is not a string when raise "foo" is used, instead it is None + and type is "foo". + So the algorithm we use is to print `str (value)' if it's not + None, otherwise we print `str (type)'. Using str (aka PyObject_Str) will fetch the error message from gdb.GdbError ("message"). */ - if (pvalue && pvalue != Py_None) - return gdbpy_obj_to_string (pvalue); + if (m_error_value && m_error_value != Py_None) + return gdbpy_obj_to_string (m_error_value); else - return gdbpy_obj_to_string (ptype); + return gdbpy_obj_to_string (m_error_type); +} + +/* See python-internal.h. */ + +gdb::unique_xmalloc_ptr<char> +gdbpy_err_fetch::type_to_string () const +{ + return gdbpy_obj_to_string (m_error_type); } /* Convert a GDB exception to the appropriate Python exception. @@ -394,16 +399,8 @@ gdb_pymodule_addobject (PyObject *module, const char *name, PyObject *object) void gdbpy_handle_exception () { - PyObject *ptype, *pvalue, *ptraceback; - - PyErr_Fetch (&ptype, &pvalue, &ptraceback); - - /* Try to fetch an error message contained within ptype, pvalue. - When fetching the error message we need to make our own copy, - we no longer own ptype, pvalue after the call to PyErr_Restore. */ - - gdb::unique_xmalloc_ptr<char> - msg (gdbpy_exception_to_string (ptype, pvalue)); + gdbpy_err_fetch fetched_error; + gdb::unique_xmalloc_ptr<char> msg = fetched_error.to_string (); if (msg == NULL) { @@ -422,12 +419,12 @@ gdbpy_handle_exception () for user errors. However, a missing message for gdb.GdbError exceptions is arguably a bug, so we flag it as such. */ - if (PyErr_GivenExceptionMatches (ptype, PyExc_KeyboardInterrupt)) + if (fetched_error.type_matches (PyExc_KeyboardInterrupt)) throw_quit ("Quit"); - else if (! PyErr_GivenExceptionMatches (ptype, gdbpy_gdberror_exc) - || msg == NULL || *msg == '\0') + else if (! fetched_error.type_matches (gdbpy_gdberror_exc) + || msg == NULL || *msg == '\0') { - PyErr_Restore (ptype, pvalue, ptraceback); + fetched_error.restore (); gdbpy_print_stack (); if (msg != NULL && *msg != '\0') error (_("Error occurred in Python: %s"), msg.get ()); @@ -435,10 +432,5 @@ gdbpy_handle_exception () error (_("Error occurred in Python.")); } else - { - Py_XDECREF (ptype); - Py_XDECREF (pvalue); - Py_XDECREF (ptraceback); - error ("%s", msg.get ()); - } + error ("%s", msg.get ()); } |