This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
Re: [python] Something rotten in exception cleanup
- From: Tom Tromey <tromey at redhat dot com>
- To: Paul Pluzhnikov <ppluzhnikov at google dot com>
- Cc: Project Archer <archer at sourceware dot org>
- Date: Tue, 16 Dec 2008 10:24:51 -0700
- Subject: Re: [python] Something rotten in exception cleanup
- References: <8ac60eac0812151810l6ee2be35v2507abb4350ba5dd@mail.gmail.com>
- Reply-to: Tom Tromey <tromey at redhat dot com>
>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:
Paul> There is something rotten in Python cleanup of exceptions:
Thanks for reporting this.
Paul> It looks like there are cleanup routines, that refer to stack
Paul> locations already popped off.
Paul> I'll try to debug this further, but posting just in case someone
Paul> can spot the problem right away.
I went ahead and looked at it, I hope that doesn't inconvenience you.
The bug is that it is not valid to "return" from inside a TRY_CATCH.
This patch fixes all the instances of this that I could find. I only
checked python/*.c.
This made the valgrind errors go away for me, using your example.
Could you try it, too?
One more bug that would not have happened in C++ ... :-)
Tom
2008-12-16 Tom Tromey <tromey@redhat.com>
* python/python-frame.c (FRAPY_REQUIRE_VALID): Use error, not
python exception.
(gdbpy_frames): Don't return inside a TRY_CATCH.
(gdbpy_current_frame): Likewise.
(gdbpy_selected_frame): Likewise.
* python/python.c (gdbpy_parameter): Don't return inside a
TRY_CATCH.
diff --git a/gdb/python/python-frame.c b/gdb/python/python-frame.c
index e6f2ada..69bb36b 100644
--- a/gdb/python/python-frame.c
+++ b/gdb/python/python-frame.c
@@ -42,14 +42,13 @@ typedef struct {
int frame_id_is_next;
} frame_object;
-#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
- do { \
- frame = frame_object_to_frame_info (frame_obj); \
- if (frame == NULL) \
- { \
- PyErr_SetString (PyExc_RuntimeError, "Frame is invalid."); \
- return NULL; \
- } \
+/* Require a valid frame. This must be called inside a TRY_CATCH, or
+ another context in which a gdb exception is allowed. */
+#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
+ do { \
+ frame = frame_object_to_frame_info (frame_obj); \
+ if (frame == NULL) \
+ error ("Frame is invalid."); \
} while (0)
static PyTypeObject frame_object_type;
@@ -382,7 +381,8 @@ gdbpy_frames (PyObject *self, PyObject *args)
if (frame_obj == NULL)
{
Py_DECREF (list);
- return NULL;
+ list = NULL;
+ break;
}
PyList_Append (list, (PyObject *) frame_obj);
@@ -396,8 +396,13 @@ gdbpy_frames (PyObject *self, PyObject *args)
"%s", except.message);
}
- tuple = PyList_AsTuple (list);
- Py_DECREF (list);
+ if (list)
+ {
+ tuple = PyList_AsTuple (list);
+ Py_DECREF (list);
+ }
+ else
+ tuple = NULL;
return tuple;
}
@@ -413,8 +418,6 @@ gdbpy_current_frame (PyObject *self, PyObject *args)
{
frame = get_current_frame ();
frame_obj = frame_info_to_frame_object (frame);
- if (frame_obj == NULL)
- return NULL;
}
GDB_PY_HANDLE_EXCEPTION (except);
@@ -432,8 +435,6 @@ gdbpy_selected_frame (PyObject *self, PyObject *args)
{
frame = get_selected_frame ("No frame is currently selected.");
frame_obj = frame_info_to_frame_object (frame);
- if (frame_obj == NULL)
- return NULL;
}
GDB_PY_HANDLE_EXCEPTION (except);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 02e5c61..9f1c8a4 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -228,6 +228,7 @@ gdbpy_parameter (PyObject *self, PyObject *args)
{
struct cmd_list_element *alias, *prefix, *cmd;
char *arg, *newarg;
+ int found = -1;
volatile struct gdb_exception except;
if (! PyArg_ParseTuple (args, "s", &arg))
@@ -237,15 +238,13 @@ gdbpy_parameter (PyObject *self, PyObject *args)
TRY_CATCH (except, RETURN_MASK_ALL)
{
- if (! lookup_cmd_composition (newarg, &alias, &prefix, &cmd))
- {
- xfree (newarg);
- return PyErr_Format (PyExc_RuntimeError,
- "could not find parameter `%s'", arg);
- }
+ found = lookup_cmd_composition (newarg, &alias, &prefix, &cmd);
}
xfree (newarg);
GDB_PY_HANDLE_EXCEPTION (except);
+ if (!found)
+ return PyErr_Format (PyExc_RuntimeError,
+ "could not find parameter `%s'", arg);
if (! cmd->var)
return PyErr_Format (PyExc_RuntimeError, "`%s' is not a parameter", arg);