pypy/module/cpyext/test/test_capsule.py::AppTestCapsule::()::test_capsule_destructor_via_gc_collect
self = <pypy.interpreter.typedef.W_ObjectObjectUserDictWeakrefable object at 0x0000021f2d73bef8>
def test_capsule_destructor_via_gc_collect(self):
# Like test_capsule_set but the C code calls PyGC_Collect() directly
# instead of going through Python's gc.collect. This mirrors what
# _testcapimodule.c does in its test_capsule() function.
# On CPython, Py_DECREF immediately calls tp_dealloc so PyGC_Collect
# is a no-op for refcounted objects. On PyPy, PyGC_Collect() must
# trigger rawrefcount collection for the destructor to be called.
module = self.import_extension('foo_cap_gc', [
("test_capsule_gc", "METH_NOARGS",
"""
PyObject *object;
const char *error = NULL;
#define FAIL(x) { error = (x); goto exit; }
#define CHECK_DESTRUCTOR \\
PyGC_Collect(); \\
PyGC_Collect(); \\
if (cap_error) { \\
FAIL(cap_error); \\
} \\
else if (!cap_destructor_count) { \\
FAIL("destructor not called!"); \\
} \\
cap_destructor_count = 0;
object = PyCapsule_New(cap_pointer, cap_name, cap_destructor);
PyCapsule_SetContext(object, cap_context);
cap_destructor(object);
CHECK_DESTRUCTOR;
Py_DECREF(object);
CHECK_DESTRUCTOR;
object = PyCapsule_New(cap_pointer, "ignored", NULL);
PyCapsule_SetPointer(object, cap_pointer);
PyCapsule_SetName(object, cap_name);
PyCapsule_SetDestructor(object, cap_destructor);
PyCapsule_SetContext(object, cap_context);
cap_destructor(object);
CHECK_DESTRUCTOR;
PyCapsule_SetDestructor(object, NULL);
Py_DECREF(object);
if (cap_destructor_count) {
FAIL("destructor called when it should not have been!");
}
exit:
if (error) {
PyErr_Format(PyExc_RuntimeError, "test_capsule: %s", error);
return NULL;
}
Py_RETURN_NONE;
#undef FAIL
#undef CHECK_DESTRUCTOR
"""),
], prologue="""
#include <Python.h>
static const char *cap_name = "capsule name";
static char *cap_pointer = "capsule pointer";
static char *cap_context = "capsule context";
static const char *cap_error = NULL;
static int cap_destructor_count = 0;
static void
cap_destructor(PyObject *o) {
cap_destructor_count++;
if (PyCapsule_GetContext(o) != cap_context) {
cap_error = "context did not match in destructor!";
} else if (PyCapsule_GetDestructor(o) != cap_destructor) {
cap_error = "destructor did not match in destructor! (woah!)";
} else if (PyCapsule_GetName(o) != cap_name) {
cap_error = "name did not match in destructor!";
} else if (PyCapsule_GetPointer(o, cap_name) != cap_pointer) {
cap_error = "pointer did not match in destructor!";
}
}
""")
> module.test_capsule_gc()
E (application-level) SystemError: <built-in function test_capsule_gc> returned a result with an exception set
[d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\test\test_capsule.py:125]:76: SystemError
---------- Captured stdout call ----------
source_0.c
Creating library d:\systemtemp\pytest\usession-py3.12-4636\foo_cap_gc-0\foo_cap_gc.lib and object d:\systemtemp\pytest\usession-py3.12-4636\foo_cap_gc-0\foo_cap_gc.exp
Generating code
Finished generating code
dealloc_trigger...
deallocating PyCapsule
dealloc_trigger DONE
dealloc_trigger...
deallocating PyCapsule
Error in cpyext, CPython compatibility layer:
The function capsule_dealloc was not supposed to fail
Fatal error in cpyext, CPython compatibility layer, calling capsule_dealloc
Either report a bug or consider not using this particular extension
---------- Captured stderr call ----------
<function PyModule_Create2 at 0x0000021f29b24a70> DONE
<function PyCapsule_New at 0x0000021f2a834548> DONE
<function PyCapsule_SetContext at 0x0000021f2a835178> DONE
<function PyGC_Collect at 0x0000021f29840db8> DONE
<function PyGC_Collect at 0x0000021f29840db8> DONE
<function PyGC_Collect at 0x0000021f29840db8> <function capsule_dealloc at 0x0000021f2a834890> DONE
DONE
<function PyGC_Collect at 0x0000021f29840db8> DONE
<function PyCapsule_New at 0x0000021f2a834548> DONE
<function PyCapsule_SetPointer at 0x0000021f2a8349f8> DONE
<function PyCapsule_SetName at 0x0000021f2a834ea8> DONE
<function PyCapsule_SetDestructor at 0x0000021f2a834c50> DONE
<function PyCapsule_SetContext at 0x0000021f2a835178> DONE
<function PyGC_Collect at 0x0000021f29840db8> <function capsule_dealloc at 0x0000021f2a834890> File "d:\pypy_stuff\pypy2.7-v7.3.18\lib_pypy\_ctypes\function.py", line 283, in f
return to_call(*args)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\ll2ctypes.py", line 895, in callback
return callback_internal(*cargs)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\ll2ctypes.py", line 872, in callback_internal
llres = container._callable(*llargs)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\object.py", line 49, in _PyPy_Free
pyobj_raw_free(ptr)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\pyobject.py", line 69, in pyobj_raw_free
lltype.free(base, flavor='raw')
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\lltype.py", line 2253, in free
leakfinder.remember_free(p._obj0)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\tool\leakfinder.py", line 95, in remember_free
raise KeyError(obj)
KeyError: <C object Array of void {'nolength': True, 'render_as_void': True} at 0x21f30150920>
Traceback (most recent call last):
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 1185, in wrapper_second_level
result = callable(space, *boxed_args)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\capsule.py", line 49, in capsule_dealloc
_dealloc(space, py_obj)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\object.py", line 71, in _dealloc
_tp_free(space, obj)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\object.py", line 63, in _tp_free
generic_cpy_call(space, pto.c_tp_free, obj_voidp)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 2128, in generic_cpy_call
return make_generic_cpy_call(FT, False, True)(space, func, *args)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 2188, in generic_cpy_call
result = call_external_function(func, *boxed_args)
File "<3674-codegen d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py:2160>", line 4, in cpy_call_external
res = funcptr(a0)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\lltype.py", line 1384, in __call__
return callb(*args)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\ll2ctypes.py", line 895, in callback
return callback_internal(*cargs)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\ll2ctypes.py", line 872, in callback_internal
llres = container._callable(*llargs)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\object.py", line 49, in _PyPy_Free
pyobj_raw_free(ptr)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\pyobject.py", line 69, in pyobj_raw_free
lltype.free(base, flavor='raw')
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\lltype.py", line 2253, in free
leakfinder.remember_free(p._obj0)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\tool\leakfinder.py", line 95, in remember_free
raise KeyError(obj)
KeyError: <C object Array of void {'nolength': True, 'render_as_void': True} at 0x21f30150920>
Traceback (most recent call last):
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 1225, in wrapper_second_level
raise not_supposed_to_fail(pname)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 1066, in not_supposed_to_fail
raise SystemError
SystemError
File "d:\pypy_stuff\pypy2.7-v7.3.18\lib_pypy\_ctypes\function.py", line 283, in f
return to_call(*args)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\ll2ctypes.py", line 895, in callback
return callback_internal(*cargs)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\rpython\rtyper\lltypesystem\ll2ctypes.py", line 872, in callback_internal
llres = container._callable(*llargs)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 1038, in wrapper
return wrapper_second_level(callable, pname, *args)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\api.py", line 1247, in wrapper_second_level
state.check_and_raise_exception(always=True)
File "d:\pypy_stuff\buildbot64\slave\own-win-x86-64\build\pypy\module\cpyext\state.py", line 87, in check_and_raise_exception
raise operror
OperationError: [<W_TypeObject 'SystemError' at 0x21f295d0d78>: W_BaseExceptionUserWeakrefable([W_UnicodeObject("KeyError(<C object Array of void {'nolength': True, 'render_as_void': True} at 0x21f30150920>,)")])]
<function PyGC_Collect at 0x0000021f29840db8> DONE
<function PyCapsule_SetDestructor at 0x0000021f2a834c50> DONE
(somefailed=True in module/cpyext/test/test_capsule.py)
builder: own-win-x86-64 build #2420+
test: pypy/module/cpyext/test/test_capsule.py::AppTestCapsule::()::test_capsule_destructor_via_gc_collect