@@ -1080,14 +1080,14 @@ set_update_impl(PySetObject *so, PyObject *args)
10801080 can be retrieved or updated in a single cache line.
10811081*/
10821082
1083+ // Build a set/frozenset left GC-untracked; the caller must _PyObject_GC_TRACK()
1084+ // it once fully built, so a half-built set is never exposed during filling.
10831085static PyObject *
1084- make_new_set (PyTypeObject * type , PyObject * iterable )
1086+ make_new_set_untracked (PyTypeObject * type , PyObject * iterable )
10851087{
10861088 assert (PyType_Check (type ));
10871089 PySetObject * so ;
10881090
1089- // Allocate untracked: the fill below runs user code, and a half-built
1090- // set must not be reachable from another thread via gc.get_objects().
10911091 so = (PySetObject * )_PyType_AllocNoTrack (type , 0 );
10921092 if (so == NULL )
10931093 return NULL ;
@@ -1107,21 +1107,39 @@ make_new_set(PyTypeObject *type, PyObject *iterable)
11071107 }
11081108 }
11091109
1110- // Track only once fully built.
1111- _PyObject_GC_TRACK (so );
11121110 return (PyObject * )so ;
11131111}
11141112
11151113static PyObject *
1116- make_new_set_basetype (PyTypeObject * type , PyObject * iterable )
1114+ make_new_set (PyTypeObject * type , PyObject * iterable )
1115+ {
1116+ PyObject * so = make_new_set_untracked (type , iterable );
1117+ if (so != NULL ) {
1118+ _PyObject_GC_TRACK (so );
1119+ }
1120+ return so ;
1121+ }
1122+
1123+ static PyObject *
1124+ make_new_set_basetype_untracked (PyTypeObject * type , PyObject * iterable )
11171125{
11181126 if (type != & PySet_Type && type != & PyFrozenSet_Type ) {
11191127 if (PyType_IsSubtype (type , & PySet_Type ))
11201128 type = & PySet_Type ;
11211129 else
11221130 type = & PyFrozenSet_Type ;
11231131 }
1124- return make_new_set (type , iterable );
1132+ return make_new_set_untracked (type , iterable );
1133+ }
1134+
1135+ static PyObject *
1136+ make_new_set_basetype (PyTypeObject * type , PyObject * iterable )
1137+ {
1138+ PyObject * so = make_new_set_basetype_untracked (type , iterable );
1139+ if (so != NULL ) {
1140+ _PyObject_GC_TRACK (so );
1141+ }
1142+ return so ;
11251143}
11261144
11271145static PyObject *
@@ -1364,7 +1382,7 @@ set_intersection(PySetObject *so, PyObject *other)
13641382 if ((PyObject * )so == other )
13651383 return set_copy_impl (so );
13661384
1367- result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
1385+ result = (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
13681386 if (result == NULL )
13691387 return NULL ;
13701388
@@ -1397,6 +1415,7 @@ set_intersection(PySetObject *so, PyObject *other)
13971415 }
13981416 Py_DECREF (key );
13991417 }
1418+ _PyObject_GC_TRACK (result );
14001419 return (PyObject * )result ;
14011420 }
14021421
@@ -1428,6 +1447,7 @@ set_intersection(PySetObject *so, PyObject *other)
14281447 Py_DECREF (result );
14291448 return NULL ;
14301449 }
1450+ _PyObject_GC_TRACK (result );
14311451 return (PyObject * )result ;
14321452 error :
14331453 Py_DECREF (it );
@@ -1737,7 +1757,7 @@ set_difference(PySetObject *so, PyObject *other)
17371757 return set_copy_and_difference (so , other );
17381758 }
17391759
1740- result = make_new_set_basetype (Py_TYPE (so ), NULL );
1760+ result = make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
17411761 if (result == NULL )
17421762 return NULL ;
17431763
@@ -1761,6 +1781,7 @@ set_difference(PySetObject *so, PyObject *other)
17611781 }
17621782 Py_DECREF (key );
17631783 }
1784+ _PyObject_GC_TRACK (result );
17641785 return result ;
17651786 }
17661787
@@ -1784,6 +1805,7 @@ set_difference(PySetObject *so, PyObject *other)
17841805 }
17851806 Py_DECREF (key );
17861807 }
1808+ _PyObject_GC_TRACK (result );
17871809 return result ;
17881810}
17891811
@@ -1970,7 +1992,8 @@ static PyObject *
19701992set_symmetric_difference_impl (PySetObject * so , PyObject * other )
19711993/*[clinic end generated code: output=270ee0b5d42b0797 input=624f6e7bbdf70db1]*/
19721994{
1973- PySetObject * result = (PySetObject * )make_new_set_basetype (Py_TYPE (so ), NULL );
1995+ PySetObject * result =
1996+ (PySetObject * )make_new_set_basetype_untracked (Py_TYPE (so ), NULL );
19741997 if (result == NULL ) {
19751998 return NULL ;
19761999 }
@@ -1982,6 +2005,7 @@ set_symmetric_difference_impl(PySetObject *so, PyObject *other)
19822005 Py_DECREF (result );
19832006 return NULL ;
19842007 }
2008+ _PyObject_GC_TRACK (result );
19852009 return (PyObject * )result ;
19862010}
19872011
0 commit comments