]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-152235: Defer GC tracking of set and frozenset to end of construction ...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 26 Jun 2026 03:00:03 +0000 (05:00 +0200)
committerGitHub <noreply@github.com>
Fri, 26 Jun 2026 03:00:03 +0000 (03:00 +0000)
gh-152235: Defer GC tracking of set and frozenset to end of construction (gh-152237)
(cherry picked from commit 908f438e198a753d40d1166b5f8725e650a9ed6e)

Co-authored-by: Donghee Na <donghee.na@python.org>
Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-05-49-13.gh-issue-152235.YU20T9.rst [new file with mode: 0644]
Objects/setobject.c

diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-05-49-13.gh-issue-152235.YU20T9.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-06-26-05-49-13.gh-issue-152235.YU20T9.rst
new file mode 100644 (file)
index 0000000..8d386ad
--- /dev/null
@@ -0,0 +1,2 @@
+Defer GC tracking of a :class:`set` or :class:`frozenset` to the end of its
+construction from iterable. Patch by Donghee Na.
index b15e63131a830066e01fa584b0b600cbbc5c3b64..332552aa0822e17c20f0aa85e39dcff3a1b4b3ac 100644 (file)
@@ -1143,7 +1143,9 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
     assert(PyType_Check(type));
     PySetObject *so;
 
-    so = (PySetObject *)type->tp_alloc(type, 0);
+    // Allocate untracked: the fill below runs user code, and a half-built
+    // set must not be reachable from another thread via gc.get_objects().
+    so = (PySetObject *)_PyType_AllocNoTrack(type, 0);
     if (so == NULL)
         return NULL;
 
@@ -1162,6 +1164,8 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
         }
     }
 
+    // Track only once fully built.
+    _PyObject_GC_TRACK(so);
     return (PyObject *)so;
 }
 
@@ -2603,7 +2607,7 @@ PyTypeObject PySet_Type = {
     0,                                  /* tp_descr_set */
     0,                                  /* tp_dictoffset */
     set_init,                           /* tp_init */
-    PyType_GenericAlloc,                /* tp_alloc */
+    _PyType_AllocNoTrack,               /* tp_alloc */
     set_new,                            /* tp_new */
     PyObject_GC_Del,                    /* tp_free */
     .tp_vectorcall = set_vectorcall,
@@ -2695,7 +2699,7 @@ PyTypeObject PyFrozenSet_Type = {
     0,                                  /* tp_descr_set */
     0,                                  /* tp_dictoffset */
     0,                                  /* tp_init */
-    PyType_GenericAlloc,                /* tp_alloc */
+    _PyType_AllocNoTrack,               /* tp_alloc */
     frozenset_new,                      /* tp_new */
     PyObject_GC_Del,                    /* tp_free */
     .tp_vectorcall = frozenset_vectorcall,