Skip to content

Commit

Permalink
Merge pull request #248 from enthought/fix/bogus-incref
Browse files Browse the repository at this point in the history
Fix reference counting bug (extra Py_INCREF) in _has_traits_notifiers.
  • Loading branch information
mdickinson committed Jul 16, 2015
2 parents 7e2132c + 20dd732 commit 4946df0
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Fixes
* Fix incorrect behaviour of ``check_implements`` for overridden methods.
(#192)
* Fix error when trying to listen to traits using list bracket notation. (#195)
* Fix reference leak in ``CHasTraits._notifiers``. (#248)


Release 4.5.0
Expand Down
16 changes: 10 additions & 6 deletions traits/ctraits.c
Original file line number Diff line number Diff line change
Expand Up @@ -1428,19 +1428,23 @@ _has_traits_notifiers ( has_traits_object * obj, PyObject * args ) {
PyObject * list;
int force_create;

if ( !PyArg_ParseTuple( args, "i", &force_create ) )
if ( !PyArg_ParseTuple( args, "i", &force_create ) )
return NULL;

result = (PyObject *) obj->notifiers;
if ( result == NULL ) {
result = Py_None;
if ( force_create && ((list = PyList_New( 0 )) != NULL) ) {
obj->notifiers = (PyListObject *) (result = list);
Py_INCREF( result );
if ( force_create ) {
list = PyList_New(0);
if (list == NULL)
return NULL;
obj->notifiers = (PyListObject *)list;
result = list;
}
else {
result = Py_None;
}
}
Py_INCREF( result );

return result;
}

Expand Down
21 changes: 21 additions & 0 deletions traits/tests/test_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,27 @@ def test_init_list_depends(self):
list_test.b[0] = 0
self.assertEqual(list_test.events_received, 3)

def test_has_traits_notifiers_refleak(self):
# Regression test for issue described in
# https://github.com/enthought/traits/pull/248
def handler():
pass

def f():
obj = HasTraits()
obj.on_trait_change(handler)

# Warmup.
for _ in xrange(10):
f()
gc.collect()

refs = len(gc.get_objects())
f()
gc.collect()
refs2 = len(gc.get_objects())
self.assertEqual(refs, refs2)


if __name__ == '__main__':
unittest.main()

0 comments on commit 4946df0

Please sign in to comment.