Attached is a patch that fixes several reference leaks in gtkmodule.c that
was made against the version released is pygtk-0.6.3. The problems it
fixes are:
* When a widget is created but is not added to a container, it was never
released since gtk_object_sink was never called. I fixed this by
calling gtk_object_sink in PyGtk_New, which isn't ideal, but a change
in how constructor functions are generated would be required to avoid
this.
* PyList_Append does not consume the reference of the element being
appended. I inserted Py_DECREF in the aappropiate places.
* Py_BuildValue also does not consume references that are passed to it.
Since this is used to build the tuples that are attached to the signal
handlers, the callback function objects were never released. I fixed
the signal connection functions, but did not fix other uses of
Py_BuildValue.
I also inserted error detection code around my changes where it was
needed. Please let me know if I should change anything in these changes to
get them included in future versions of pygtk.
Thanks,
John
*** gtkmodule.c Wed Dec 15 12:46:18 1999
--- /home/jpe/down/pygtk-0.6.3/gtkmodule.c Thu Sep 30 01:33:14 1999
***************
*** 104,110 ****
return NULL;
self->obj = go;
gtk_object_ref(self->obj);
- gtk_object_sink(self->obj);
return (PyObject *)self;
}
--- 104,109 ----
***************
*** 2300,2319 ****
} else if (!strcmp(key, "children")) {
GtkCTreeNode *node = GTK_CTREE_ROW(self->node)->children;
PyObject *ret = PyList_New(0);
- if ( PyErr_Occurred() )
- return NULL;
while (node) {
! PyObject *py_node = PyGtkCTreeNode_New(node);
! if ( PyErr_Occurred() ) {
! Py_DECREF(ret);
! return NULL;
! }
! PyList_Append(ret, py_node);
! Py_DECREF(py_node);
! if ( PyErr_Occurred() ) {
! Py_DECREF(ret);
! return NULL;
! }
node = GTK_CTREE_ROW(node)->sibling;
}
return ret;
--- 2299,2306 ----
} else if (!strcmp(key, "children")) {
GtkCTreeNode *node = GTK_CTREE_ROW(self->node)->children;
PyObject *ret = PyList_New(0);
while (node) {
! PyList_Append(ret, PyGtkCTreeNode_New(node));
node = GTK_CTREE_ROW(node)->sibling;
}
return ret;
***************
*** 3253,3259 ****
}
pos++;
}
! return arg;
}
static PyObject *_wrap_gtk_signal_connect(PyObject *self, PyObject *args) {
--- 3240,3246 ----
}
pos++;
}
! return arg;
}
static PyObject *_wrap_gtk_signal_connect(PyObject *self, PyObject *args) {
***************
*** 3269,3283 ****
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
!
! if ( extra != NULL )
! Py_INCREF(extra);
else
! extra = PyTuple_New(0);
data = Py_BuildValue("(OO)", func, extra);
- Py_DECREF(extra);
- if ( PyErr_Occurred() )
- return NULL;
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, FALSE);
--- 3256,3267 ----
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
! Py_INCREF(func);
! if (extra)
! Py_INCREF(extra);
else
! extra = PyTuple_New(0);
data = Py_BuildValue("(OO)", func, extra);
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, FALSE);
***************
*** 3297,3311 ****
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
if (extra)
Py_INCREF(extra);
else
extra = PyTuple_New(0);
data = Py_BuildValue("(OO)", func, extra);
- Py_DECREF(extra);
- if ( PyErr_Occurred() )
- return NULL;
-
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, TRUE);
--- 3281,3292 ----
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
+ Py_INCREF(func);
if (extra)
Py_INCREF(extra);
else
extra = PyTuple_New(0);
data = Py_BuildValue("(OO)", func, extra);
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, TRUE);
***************
*** 3326,3340 ****
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
if (extra)
Py_INCREF(extra);
else
extra = PyTuple_New(0);
data = Py_BuildValue("(OOO)", func, extra, other);
- Py_DECREF(extra);
- if ( PyErr_Occurred() )
- return NULL;
-
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, FALSE);
--- 3307,3319 ----
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
+ Py_INCREF(func);
if (extra)
Py_INCREF(extra);
else
extra = PyTuple_New(0);
+ Py_INCREF(other);
data = Py_BuildValue("(OOO)", func, extra, other);
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, FALSE);
***************
*** 3355,3370 ****
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
!
if (extra)
Py_INCREF(extra);
else
extra = PyTuple_New(0);
data = Py_BuildValue("(OOO)", func, extra, other);
- Py_DECREF(extra);
- if ( PyErr_Occurred() )
- return NULL;
-
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, TRUE);
--- 3334,3346 ----
PyErr_SetString(PyExc_TypeError, "third argument must be callable");
return NULL;
}
! Py_INCREF(func);
if (extra)
Py_INCREF(extra);
else
extra = PyTuple_New(0);
+ Py_INCREF(other);
data = Py_BuildValue("(OOO)", func, extra, other);
signum = gtk_signal_connect_full(PyGtk_Get(obj), name, NULL,
(GtkCallbackMarshal)PyGtk_CallbackMarshal,
data, PyGtk_DestroyNotify, FALSE, TRUE);
***************
*** 3932,3962 ****
PyObject *obj;
GList *list, *tmp;
PyObject *py_list;
- PyObject *gtk_obj;
if(!PyArg_ParseTuple(args,"O!:gtk_container_children", &PyGtk_Type, &obj))
return NULL;
list = gtk_container_children(GTK_CONTAINER(PyGtk_Get(obj)));
-
py_list = PyList_New(0);
! if ( PyErr_Occurred() ) {
! g_list_free(list);
! return NULL;
! }
!
! for (tmp = list; tmp != NULL; tmp = tmp->next) {
! gtk_obj = PyGtk_New(GTK_OBJECT(tmp->data));
! if ( PyErr_Occurred() ) {
! g_list_free(list);
! return NULL;
! }
! PyList_Append(py_list, gtk_obj);
! Py_DECREF(gtk_obj);
! if ( PyErr_Occurred() ) {
! g_list_free(list);
! return NULL;
! }
! }
g_list_free(list);
return py_list;
}
--- 3908,3920 ----
PyObject *obj;
GList *list, *tmp;
PyObject *py_list;
if(!PyArg_ParseTuple(args,"O!:gtk_container_children", &PyGtk_Type, &obj))
return NULL;
list = gtk_container_children(GTK_CONTAINER(PyGtk_Get(obj)));
py_list = PyList_New(0);
! for (tmp = list; tmp != NULL; tmp = tmp->next)
! PyList_Append(py_list, PyGtk_New(GTK_OBJECT(tmp->data)));
g_list_free(list);
return py_list;
}
***************
*** 4138,4166 ****
static PyObject *_wrap_gtk_clist_get_selection(PyObject *self, PyObject *args) {
GList *selection;
guint row;
! PyObject *clist, *ret, *py_int;
if (!PyArg_ParseTuple(args, "O!:gtk_clist_get_selection", &PyGtk_Type,
&clist))
return NULL;
ret = PyList_New(0);
- if ( PyErr_Occurred() )
- return NULL;
-
for (selection = GTK_CLIST(PyGtk_Get(clist))->selection; selection != NULL;
selection = selection->next) {
row = (guint)selection->data;
! py_int = PyInt_FromLong(row);
! if ( PyErr_Occurred() ) {
! Py_DECREF(ret);
! return NULL;
! }
!
! PyList_Append(ret, py_int);
! Py_DECREF(py_int);
! if ( PyErr_Occurred() ) {
! Py_DECREF(ret);
! return NULL;
! }
}
return ret;
}
--- 4096,4110 ----
static PyObject *_wrap_gtk_clist_get_selection(PyObject *self, PyObject *args) {
GList *selection;
guint row;
! PyObject *clist, *ret;
if (!PyArg_ParseTuple(args, "O!:gtk_clist_get_selection", &PyGtk_Type,
&clist))
return NULL;
ret = PyList_New(0);
for (selection = GTK_CLIST(PyGtk_Get(clist))->selection; selection != NULL;
selection = selection->next) {
row = (guint)selection->data;
! PyList_Append(ret, PyInt_FromLong(row));
}
return ret;
}
***************
*** 5593,5620 ****
static PyObject *_wrap_gtk_ctree_get_selection(PyObject *self, PyObject *args) {
GList *selection;
GtkCTreeNode *node;
! PyObject *clist, *ret, *py_node;
if (!PyArg_ParseTuple(args, "O!:gtk_ctree_get_selection", &PyGtk_Type,
&clist))
return NULL;
ret = PyList_New(0);
- if ( PyErr_Occurred() )
- return NULL;
-
for (selection = GTK_CLIST(PyGtk_Get(clist))->selection; selection != NULL;
selection = selection->next) {
node = selection->data;
! py_node = PyGtkCTreeNode_New(node);
! if ( PyErr_Occurred() ) {
! Py_DECREF(ret);
! return NULL;
! }
! PyList_Append(ret, py_node);
! Py_DECREF(py_node);
! if ( PyErr_Occurred() ) {
! Py_DECREF(ret);
! return NULL;
! }
}
return ret;
}
--- 5537,5551 ----
static PyObject *_wrap_gtk_ctree_get_selection(PyObject *self, PyObject *args) {
GList *selection;
GtkCTreeNode *node;
! PyObject *clist, *ret;
if (!PyArg_ParseTuple(args, "O!:gtk_ctree_get_selection", &PyGtk_Type,
&clist))
return NULL;
ret = PyList_New(0);
for (selection = GTK_CLIST(PyGtk_Get(clist))->selection; selection != NULL;
selection = selection->next) {
node = selection->data;
! PyList_Append(ret, PyGtkCTreeNode_New(node));
}
return ret;
}