gstbus: fix refcounting in gst.Bus.set_sync_handler.

This commit is contained in:
Alessandro Decina 2009-03-17 15:03:09 +01:00
parent 4eba960ed2
commit 0fd4db686b
2 changed files with 68 additions and 6 deletions

View file

@ -155,8 +155,12 @@ override gst_bus_set_sync_handler args
static PyObject *
_wrap_gst_bus_set_sync_handler (PyGObject *self, PyObject *args)
{
PyObject *callback, *cbargs = NULL, *data;
PyObject *callback = NULL;
PyObject *cbargs = NULL;
PyObject *data = NULL;
PyObject *old_data = NULL;
gint len;
static GQuark sync_handler_data_quark = 0;
len = PyTuple_Size(args);
@ -165,26 +169,54 @@ _wrap_gst_bus_set_sync_handler (PyGObject *self, PyObject *args)
return NULL;
}
if (sync_handler_data_quark == 0)
sync_handler_data_quark = \
g_quark_from_static_string("PyGst::BusSyncHandlerData");
callback = PySequence_GetItem(args, 0);
if (callback != Py_None) {
if (!PyCallable_Check(callback)) {
Py_DECREF (callback);
PyErr_SetString(PyExc_TypeError, "callback is not callable");
return NULL;
}
cbargs = PySequence_GetSlice(args, 1, len);
if (cbargs == NULL)
if (cbargs == NULL) {
Py_DECREF (callback);
return NULL;
}
data = Py_BuildValue("(ON)", callback, cbargs);
if (data == NULL)
Py_DECREF (cbargs);
if (data == NULL) {
Py_DECREF (callback);
return NULL;
}
old_data = g_object_get_qdata (self->obj, sync_handler_data_quark);
if (old_data != NULL) {
Py_DECREF (old_data);
}
g_object_set_qdata (self->obj, sync_handler_data_quark, data);
gst_bus_set_sync_handler (GST_BUS (self->obj),
(GstBusSyncHandler) bus_sync_handler,
(GstBusSyncHandler) bus_sync_handler,
data);
} else
} else {
old_data = g_object_get_qdata (self->obj, sync_handler_data_quark);
if (old_data != NULL) {
Py_DECREF (old_data);
}
g_object_set_qdata (self->obj, sync_handler_data_quark, NULL);
gst_bus_set_sync_handler (GST_BUS (self->obj), NULL, NULL);
}
Py_DECREF (callback);
Py_INCREF(Py_None);
return Py_None;
}

View file

@ -22,6 +22,7 @@ from common import gst, unittest, TestCase
import gobject
import time
import sys
class BusSignalTest(TestCase):
def testGoodConstructor(self):
@ -109,8 +110,37 @@ class BusSignalTest(TestCase):
loop.quit()
return True
def testSyncHandlerCallbackRefcount(self):
def callback1():
pass
def callback2():
pass
bus = gst.Bus()
# set
self.failUnless(sys.getrefcount(callback1), 2)
bus.set_sync_handler(callback1)
self.failUnless(sys.getrefcount(callback1), 3)
# set again
self.failUnless(sys.getrefcount(callback1), 3)
bus.set_sync_handler(callback1)
self.failUnless(sys.getrefcount(callback1), 3)
# replace
# this erros out in gst_bus_set_sync_handler, but we need to check that
# we don't leak anyway
self.failUnless(sys.getrefcount(callback2), 2)
bus.set_sync_handler(callback2)
self.failUnless(sys.getrefcount(callback1), 2)
self.failUnless(sys.getrefcount(callback2), 3)
# unset
bus.set_sync_handler(None)
self.failUnless(sys.getrefcount(callback2), 2)
class BusAddWatchTest(TestCase):
def testADumbExample(self):