+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.
+
2019-01-03 Andrew Burgess <andrew.burgess@embecosm.com>
* linux-nat.c (delete_lwp_cleanup): Delete.
{
if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
{
- PyObject *type, *value, *trace;
-
- PyErr_Fetch (&type, &value, &trace);
-
- gdbpy_ref<> type_ref (type);
- gdbpy_ref<> value_ref (value);
- gdbpy_ref<> trace_ref (trace);
-
- gdb::unique_xmalloc_ptr<char>
- msg (gdbpy_exception_to_string (type, value));
+ gdbpy_err_fetch fetched_error;
+ gdb::unique_xmalloc_ptr<char> msg = fetched_error.to_string ();
if (msg == NULL || *msg == '\0')
fprintf_filtered (stream, _("<error reading variable>"));
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.
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)
{
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 ());
error (_("Error occurred in Python."));
}
else
- {
- Py_XDECREF (ptype);
- Py_XDECREF (pvalue);
- Py_XDECREF (ptraceback);
- error ("%s", msg.get ());
- }
+ error ("%s", msg.get ());
}
ULONGEST instead. */
if (PyErr_ExceptionMatches (PyExc_OverflowError))
{
- PyObject *etype, *evalue, *etraceback;
-
- PyErr_Fetch (&etype, &evalue, &etraceback);
+ gdbpy_err_fetch fetched_error;
gdbpy_ref<> zero (PyInt_FromLong (0));
/* Check whether obj is positive. */
value = value_from_ulongest (builtin_type_upylong, ul);
}
else
- /* There's nothing we can do. */
- PyErr_Restore (etype, evalue, etraceback);
+ {
+ /* There's nothing we can do. */
+ fetched_error.restore ();
+ }
}
}
else
/* If we got a memory error, just use the text as the item. */
if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
{
- PyObject *type, *value, *trace;
-
- PyErr_Fetch (&type, &value, &trace);
- gdb::unique_xmalloc_ptr<char>
- value_str (gdbpy_exception_to_string (type, value));
- Py_XDECREF (type);
- Py_XDECREF (value);
- Py_XDECREF (trace);
+ gdbpy_err_fetch fetched_error;
+ gdb::unique_xmalloc_ptr<char> value_str = fetched_error.to_string ();
if (value_str == NULL)
{
gdbpy_print_stack ();
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
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
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,
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 ()
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;
/* 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",
{
}
END_CATCH
-
- Py_XDECREF (ptype);
- Py_XDECREF (pvalue);
- Py_XDECREF (ptraceback);
}
}