Skip to content

gh-152235: Defer GC tracking during the lock-free fill in set.__init__ - #153079

Closed
corona10 wants to merge 1 commit into
python:mainfrom
corona10:gh-152235-set-init
Closed

gh-152235: Defer GC tracking during the lock-free fill in set.__init__#153079
corona10 wants to merge 1 commit into
python:mainfrom
corona10:gh-152235-set-init

Conversation

@corona10

@corona10corona10 commented Jul 5, 2026

Copy link
Copy Markdown
Member

@corona10

Copy link
Copy Markdown
MemberAuthor

@vstinner@methane

Final PR of the set: list already has TSan-safe initialization, and this brings set.init up to the same level of protection.

list___init___impl(PyListObject*self, PyObject*iterable)
/*[clinic end generated code: output=0f3c21379d01de48 input=b3f3fe7206af8f6b]*/
{
/* Verify list invariants established by PyType_GenericAlloc() */
assert(0 <= Py_SIZE(self));
assert(Py_SIZE(self) <= self->allocated||self->allocated==-1);
assert(self->ob_item!=NULL||
self->allocated==0||self->allocated==-1);
/* Empty previous contents */
if (self->ob_item!=NULL) {
Py_BEGIN_CRITICAL_SECTION(self);
list_clear(self);
Py_END_CRITICAL_SECTION();
}
if (iterable!=NULL) {
if (_list_extend(self, iterable) <0) {
return-1;
}
}
return0;
}

_list_extend(PyListObject*self, PyObject*iterable)
{
// Special case:
// lists and tuples which can use PySequence_Fast ops
intres=-1;
if ((PyObject*)self==iterable) {
Py_BEGIN_CRITICAL_SECTION(self);
res=list_inplace_repeat_lock_held(self, 2);
Py_END_CRITICAL_SECTION();
}
elseif (PyList_CheckExact(iterable)) {
Py_BEGIN_CRITICAL_SECTION2(self, iterable);
res=list_extend_lock_held(self, iterable);
Py_END_CRITICAL_SECTION2();
}
elseif (PyTuple_CheckExact(iterable)) {
Py_BEGIN_CRITICAL_SECTION(self);
res=list_extend_lock_held(self, iterable);
Py_END_CRITICAL_SECTION();
}
elseif (PyAnySet_CheckExact(iterable)) {
Py_BEGIN_CRITICAL_SECTION2(self, iterable);
res=list_extend_set(self, (PySetObject*)iterable);
Py_END_CRITICAL_SECTION2();
}
elseif (PyDict_CheckExact(iterable)) {
Py_BEGIN_CRITICAL_SECTION2(self, iterable);
res=list_extend_dict(self, (PyDictObject*)iterable, 0/*keys*/);
Py_END_CRITICAL_SECTION2();
}
elseif (Py_IS_TYPE(iterable, &PyDictKeys_Type)) {
PyDictObject*dict= ((_PyDictViewObject*)iterable)->dv_dict;
Py_BEGIN_CRITICAL_SECTION2(self, dict);
res=list_extend_dict(self, dict, 0/*keys*/);
Py_END_CRITICAL_SECTION2();
}
elseif (Py_IS_TYPE(iterable, &PyDictValues_Type)) {
PyDictObject*dict= ((_PyDictViewObject*)iterable)->dv_dict;
Py_BEGIN_CRITICAL_SECTION2(self, dict);
res=list_extend_dict(self, dict, 1/*values*/);
Py_END_CRITICAL_SECTION2();
}
elseif (Py_IS_TYPE(iterable, &PyDictItems_Type)) {
PyDictObject*dict= ((_PyDictViewObject*)iterable)->dv_dict;
Py_BEGIN_CRITICAL_SECTION2(self, dict);
res=list_extend_dictitems(self, dict);
Py_END_CRITICAL_SECTION2();
}
else {
Py_BEGIN_CRITICAL_SECTION(self);
res=list_extend_iter_lock_held(self, iterable);
Py_END_CRITICAL_SECTION();
}
returnres;
}

@vstinner

Copy link
Copy Markdown
Member

The issue title is "Need to defer GC tracking of frozenset/set construction", but in fact, the problem only arises for frozenset.

PyFrozenSet_Type defines tp_new (frozenset_new) but has no tp_init function.

PySet_Type defines tp_new (set_new) and tp_init (set_init).

So changing set_init() only impacts the mutable set. I don't see which problem you are trying to solve. It's fine to mutate a set object.

@corona10

Copy link
Copy Markdown
MemberAuthor

Yeah we don't need to handle

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs backport to 3.13bugs and security fixesneeds backport to 3.14bugs and security fixesneeds backport to 3.15pre-release feature fixes, bugs and security fixesskip newstopic-free-threading

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@corona10@vstinner