Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r1278:e67e5b69f47b
Date: 2013-07-16 16:03 +0200
http://bitbucket.org/cffi/cffi/changeset/e67e5b69f47b/

Log:    A test, and start to work on a fix, which doesn't work so far

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -1422,10 +1422,28 @@
 
 static int cdata_traverse(CDataObject *cd, visitproc visit, void *arg)
 {
+    /* XXX needs Py_TPFLAGS_HAVE_GC */
     Py_VISIT(cd->c_type);
     return 0;
 }
 
+static int cdataowning_traverse(CDataObject *cd, visitproc visit, void *arg)
+{
+    if (cd->c_type->ct_flags & CT_IS_PTR_TO_OWNED) {
+        Py_VISIT(((CDataObject_own_structptr *)cd)->structobj);
+    }
+    else if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {
+        PyObject *x = (PyObject *)(cd->c_data + 42);
+        Py_VISIT(x);
+    }
+    else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {
+        ffi_closure *closure = (ffi_closure *)cd->c_data;
+        PyObject *args = (PyObject *)(closure->user_data);
+        Py_VISIT(args);
+    }
+    return cdata_traverse(cd, visit, arg);
+}
+
 static PyObject *cdata_float(CDataObject *cd);  /*forward*/
 
 static PyObject *convert_cdata_to_enum_string(CDataObject *cd, int both)
@@ -2427,7 +2445,7 @@
     0,                                          /* tp_as_buffer */
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
     0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
+    (traverseproc)cdataowning_traverse,         /* tp_traverse */
     0,                                          /* tp_clear */
     0,                                          /* tp_richcompare */
     0,                                          /* tp_weaklistoffset */
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -2771,6 +2771,20 @@
     assert wr() is None
     py.test.raises(RuntimeError, from_handle, cast(BCharP, 0))
 
+def test_new_handle_cycle():
+    import _weakref
+    BVoidP = new_pointer_type(new_void_type())
+    class A(object):
+        pass
+    o = A()
+    o.cycle = newp_handle(BVoidP, o)
+    wr = _weakref.ref(o)
+    del o
+    for i in range(3):
+        if wr() is not None:
+            import gc; gc.collect()
+    assert wr() is None
+
 def _test_bitfield_details(flag):
     BChar = new_primitive_type("char")
     BShort = new_primitive_type("short")
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to