Skip to content

Commit

Permalink
pythongh-124538: Fix crash when using gc.get_referents on an untrac…
Browse files Browse the repository at this point in the history
…ked capsule object (pythonGH-124559)

(cherry picked from commit f923605)

Co-authored-by: Peter Bierma <[email protected]>
  • Loading branch information
ZeroIntensity authored and miss-islington committed Sep 26, 2024
1 parent 9f2e6ca commit bf79314
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 3 deletions.
18 changes: 18 additions & 0 deletions Lib/test/test_gc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,24 @@ class Z:
callback.assert_not_called()
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):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed crash when using :func:`gc.get_referents` on a capsule object.
10 changes: 7 additions & 3 deletions Objects/capsule.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,14 @@ static int
capsule_traverse(PyCapsule *capsule, visitproc visit, void *arg)
{
// Capsule object is only tracked by the GC
// if _PyCapsule_SetTraverse() is called
assert(capsule->traverse_func != NULL);
// if _PyCapsule_SetTraverse() is called, but
// 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;
}


Expand Down

0 comments on commit bf79314

Please sign in to comment.