mirror of
https://github.com/python/cpython.git
synced 2025-10-04 14:15:45 +00:00
[3.13] gh-127521: Mark list as "shared" before resizing if necessary (GH-127524) (GH-127533)
In the free threading build, if a non-owning thread resizes a list,
it must use QSBR to free the old list array because there may be a
concurrent access (without a lock) from the owning thread.
To match the pattern in dictobject.c, we just mark the list as "shared"
before resizing if it's from a non-owning thread and not already marked
as shared.
(cherry picked from commit c7dec02de2
)
Co-authored-by: Sam Gross <colesbury@gmail.com>
This commit is contained in:
parent
a853610282
commit
e546876d83
1 changed files with 20 additions and 0 deletions
|
@ -77,6 +77,20 @@ free_list_items(PyObject** items, bool use_qsbr)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_shared_on_resize(PyListObject *self)
|
||||||
|
{
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
// Ensure that the list array is freed using QSBR if we are not the
|
||||||
|
// owning thread.
|
||||||
|
if (!_Py_IsOwnedByCurrentThread((PyObject *)self) &&
|
||||||
|
!_PyObject_GC_IS_SHARED(self))
|
||||||
|
{
|
||||||
|
_PyObject_GC_SET_SHARED(self);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Ensure ob_item has room for at least newsize elements, and set
|
/* Ensure ob_item has room for at least newsize elements, and set
|
||||||
* ob_size to newsize. If newsize > ob_size on entry, the content
|
* ob_size to newsize. If newsize > ob_size on entry, the content
|
||||||
* of the new slots at exit is undefined heap trash; it's the caller's
|
* of the new slots at exit is undefined heap trash; it's the caller's
|
||||||
|
@ -126,6 +140,8 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
|
||||||
if (newsize == 0)
|
if (newsize == 0)
|
||||||
new_allocated = 0;
|
new_allocated = 0;
|
||||||
|
|
||||||
|
ensure_shared_on_resize(self);
|
||||||
|
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
_PyListArray *array = list_allocate_array(new_allocated);
|
_PyListArray *array = list_allocate_array(new_allocated);
|
||||||
if (array == NULL) {
|
if (array == NULL) {
|
||||||
|
@ -842,6 +858,9 @@ list_clear_impl(PyListObject *a, bool is_resize)
|
||||||
Py_XDECREF(items[i]);
|
Py_XDECREF(items[i]);
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
if (is_resize) {
|
||||||
|
ensure_shared_on_resize(a);
|
||||||
|
}
|
||||||
bool use_qsbr = is_resize && _PyObject_GC_IS_SHARED(a);
|
bool use_qsbr = is_resize && _PyObject_GC_IS_SHARED(a);
|
||||||
#else
|
#else
|
||||||
bool use_qsbr = false;
|
bool use_qsbr = false;
|
||||||
|
@ -3107,6 +3126,7 @@ keyfunc_fail:
|
||||||
Py_XDECREF(final_ob_item[i]);
|
Py_XDECREF(final_ob_item[i]);
|
||||||
}
|
}
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
ensure_shared_on_resize(self);
|
||||||
bool use_qsbr = _PyObject_GC_IS_SHARED(self);
|
bool use_qsbr = _PyObject_GC_IS_SHARED(self);
|
||||||
#else
|
#else
|
||||||
bool use_qsbr = false;
|
bool use_qsbr = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue