Merged revisions 78380 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r78380 | thomas.heller | 2010-02-23 21:11:44 +0100 (Di, 23 Feb 2010) | 4 lines

  ctypes CThunkObject was not registered correctly with the cycle
  garbage collector, leading to possible leaks when using callback
  functions.
........
diff --git a/Lib/ctypes/test/test_callbacks.py b/Lib/ctypes/test/test_callbacks.py
index 1bef33f..1466f26 100644
--- a/Lib/ctypes/test/test_callbacks.py
+++ b/Lib/ctypes/test/test_callbacks.py
@@ -118,6 +118,22 @@
         prototype = self.functype.__func__(object)
         self.assertRaises(TypeError, prototype, lambda: None)
 
+    def test_issue_7959(self):
+        proto = self.functype.__func__(None)
+
+        class X(object):
+            def func(self): pass
+            def __init__(self):
+                self.v = proto(self.func)
+
+        import gc
+        for i in range(32):
+            X()
+        gc.collect()
+        live = [x for x in gc.get_objects()
+                if isinstance(x, X)]
+        self.assertEqual(len(live), 0)
+
 try:
     WINFUNCTYPE
 except NameError:
diff --git a/Misc/NEWS b/Misc/NEWS
index 202c8fd..6abe1e2 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -254,6 +254,9 @@
 Library
 -------
 
+- Issue #7959: ctypes callback functions are now registered correctly
+  with the cylce garbage collector.
+
 - Issue #5801: removed spurious empty lines in wsgiref.
 
 - Issue #6666: fix bug in trace.py that applied the list of directories
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index 6e44080..5cf0441 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -18,7 +18,7 @@
 	Py_XDECREF(self->restype);
 	if (self->pcl)
 		_ctypes_free_closure(self->pcl);
-	PyObject_Del(self);
+	PyObject_GC_Del(self);
 }
 
 static int
@@ -61,7 +61,7 @@
 	0,					/* tp_getattro */
 	0,					/* tp_setattro */
 	0,					/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT,			/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,			/* tp_flags */
 	"CThunkObject",				/* tp_doc */
 	CThunkObject_traverse,			/* tp_traverse */
 	CThunkObject_clear,	       		/* tp_clear */
@@ -332,7 +332,7 @@
 	CThunkObject *p;
 	int i;
 
-	p = PyObject_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
+	p = PyObject_GC_NewVar(CThunkObject, &PyCThunk_Type, nArgs);
 	if (p == NULL) {
 		PyErr_NoMemory();
 		return NULL;
@@ -347,6 +347,7 @@
 	
 	for (i = 0; i < nArgs + 1; ++i)
 		p->atypes[i] = NULL;
+	PyObject_GC_Track((PyObject *)p);
 	return p;
 }