mirror of https://github.com/python/cpython
gh-124538: Fix crash when using `gc.get_referents` on an untracked capsule object (#124559)
This commit is contained in:
parent
0387c34f7c
commit
f923605658
|
@ -1048,6 +1048,24 @@ class GCTests(unittest.TestCase):
|
||||||
callback.assert_not_called()
|
callback.assert_not_called()
|
||||||
gc.enable()
|
gc.enable()
|
||||||
|
|
||||||
|
@cpython_only
|
||||||
|
def test_get_referents_on_capsule(self):
|
||||||
|
# gh-124538: Calling gc.get_referents() on an untracked capsule must not crash.
|
||||||
|
import _datetime
|
||||||
|
import _socket
|
||||||
|
untracked_capsule = _datetime.datetime_CAPI
|
||||||
|
tracked_capsule = _socket.CAPI
|
||||||
|
|
||||||
|
# For whoever sees this in the future: if this is failing
|
||||||
|
# after making datetime's capsule tracked, that's fine -- this isn't something
|
||||||
|
# users are relying on. Just find a different capsule that is untracked.
|
||||||
|
self.assertFalse(gc.is_tracked(untracked_capsule))
|
||||||
|
self.assertTrue(gc.is_tracked(tracked_capsule))
|
||||||
|
|
||||||
|
self.assertEqual(len(gc.get_referents(untracked_capsule)), 0)
|
||||||
|
gc.get_referents(tracked_capsule)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IncrementalGCTests(unittest.TestCase):
|
class IncrementalGCTests(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fixed crash when using :func:`gc.get_referents` on a capsule object.
|
|
@ -317,12 +317,16 @@ static int
|
||||||
capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg)
|
capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
// Capsule object is only tracked by the GC
|
// Capsule object is only tracked by the GC
|
||||||
// if _PyCapsule_SetTraverse() is called
|
// if _PyCapsule_SetTraverse() is called, but
|
||||||
assert(capsule->traverse_func != NULL);
|
// this can still be manually triggered by gc.get_referents()
|
||||||
|
|
||||||
|
if (capsule->traverse_func != NULL) {
|
||||||
return capsule->traverse_func((PyObject*)capsule, visit, arg);
|
return capsule->traverse_func((PyObject*)capsule, visit, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
capsule_clear(PyCapsule *capsule)
|
capsule_clear(PyCapsule *capsule)
|
||||||
|
|
Loading…
Reference in New Issue