diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c index 14efd79..f305b01 100644 --- a/gdb/python/py-value.c +++ b/gdb/python/py-value.c @@ -143,7 +143,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords) } value_obj->value = value; - value_incref (value); + release_value_or_incref (value); value_obj->address = NULL; value_obj->type = NULL; note_value (value_obj); @@ -267,6 +267,7 @@ valpy_cast (PyObject *self, PyObject *args) { PyObject *type_obj; struct type *type; + PyObject *res_obj = NULL; struct value *res_val = NULL; /* Initialize to appease gcc warning. */ volatile struct gdb_exception except; @@ -305,8 +306,10 @@ valpy_getitem (PyObject *self, PyObject *key) { value_object *self_value = (value_object *) self; char *field = NULL; + PyObject *res_obj = NULL; struct value *res_val = NULL; volatile struct gdb_exception except; + struct value *mark = value_mark (); if (gdbpy_is_string (key)) { @@ -344,9 +347,13 @@ valpy_getitem (PyObject *self, PyObject *key) } xfree (field); - GDB_PY_HANDLE_EXCEPTION (except); + GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP (except, mark); + + if (res_val) + res_obj = value_to_value_object (res_val); - return res_val ? value_to_value_object (res_val) : NULL; + value_free_to_mark (mark); + return res_obj; } static int @@ -427,8 +434,10 @@ enum valpy_opcode static PyObject * valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) { + PyObject *res_obj = NULL; struct value *res_val = NULL; /* Initialize to appease gcc warning. */ volatile struct gdb_exception except; + struct value *mark = value_mark (); TRY_CATCH (except, RETURN_MASK_ALL) { @@ -519,9 +528,13 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other) break; } } - GDB_PY_HANDLE_EXCEPTION (except); + GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP (except, mark); + + if (res_val) + res_obj = value_to_value_object (res_val); - return res_val ? value_to_value_object (res_val) : NULL; + value_free_to_mark (mark); + return res_obj; } static PyObject * @@ -684,6 +697,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) int result = 0; struct value *value_other; volatile struct gdb_exception except; + struct value *mark = value_mark (); if (other == Py_None) /* Comparing with None is special. From what I can tell, in Python @@ -742,6 +756,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) break; } } + value_free_to_mark (mark); GDB_PY_HANDLE_EXCEPTION (except); /* In this case, the Python exception has already been set. */ @@ -851,7 +866,7 @@ value_to_value_object (struct value *val) if (val_obj != NULL) { val_obj->value = val; - value_incref (val); + release_value_or_incref (val); val_obj->address = NULL; val_obj->type = NULL; note_value (val_obj); diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h index 47662d9..309ee5b 100644 --- a/gdb/python/python-internal.h +++ b/gdb/python/python-internal.h @@ -149,11 +149,17 @@ PyObject *gdbpy_parameter_value (enum var_types, void *); /* Use this after a TRY_EXCEPT to throw the appropriate Python exception. */ #define GDB_PY_HANDLE_EXCEPTION(Exception) \ + GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP(Exception, NULL) + +#define GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP(Exception, mark) \ do { \ - if (Exception.reason < 0) \ + if (Exception.reason < 0) { \ + if (mark) \ + value_free_to_mark (mark); \ return PyErr_Format (Exception.reason == RETURN_QUIT \ ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \ "%s", Exception.message); \ + } \ } while (0) /* Use this after a TRY_EXCEPT to throw the appropriate Python diff --git a/gdb/value.c b/gdb/value.c index 2f31185..9187a7f 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -691,7 +691,7 @@ free_all_values (void) /* Remove VAL from the chain all_values so it will not be freed automatically. */ -void +int release_value (struct value *val) { struct value *v; @@ -699,7 +699,7 @@ release_value (struct value *val) if (all_values == val) { all_values = val->next; - return; + return 1; } for (v = all_values; v; v = v->next) @@ -707,9 +707,21 @@ release_value (struct value *val) if (v->next == val) { v->next = val->next; - break; + return 1; } } + + return 0; +} + +/* Release VAL or increment its reference count if + it was released already */ + +void +release_value_or_incref (struct value *val) +{ + if (release_value (val) == 0) + value_incref (val); } /* Release all values up to mark */ diff --git a/gdb/value.h b/gdb/value.h index 0da7031..5705210 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -595,7 +595,9 @@ extern void value_free (struct value *val); extern void free_all_values (void); -extern void release_value (struct value *val); +extern int release_value (struct value *val); + +extern void release_value_or_incref (struct value *val); extern int record_latest_value (struct value *val);