https://github.com/python/cpython/commit/c7dec02de2ed4baf3cd22ad094350265b52c18af
commit: c7dec02de2ed4baf3cd22ad094350265b52c18af
branch: main
author: Sam Gross <[email protected]>
committer: colesbury <[email protected]>
date: 2024-12-02T14:38:26-05:00
summary:
gh-127521: Mark list as "shared" before resizing if necessary (#127524)
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.
files:
M Objects/listobject.c
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 4b24f4a428e18b..8abe9e8933420b 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -68,6 +68,20 @@ free_list_items(PyObject** items, bool use_qsbr)
#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
* 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
@@ -117,6 +131,8 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
if (newsize == 0)
new_allocated = 0;
+ ensure_shared_on_resize(self);
+
#ifdef Py_GIL_DISABLED
_PyListArray *array = list_allocate_array(new_allocated);
if (array == NULL) {
@@ -804,6 +820,9 @@ list_clear_impl(PyListObject *a, bool is_resize)
Py_XDECREF(items[i]);
}
#ifdef Py_GIL_DISABLED
+ if (is_resize) {
+ ensure_shared_on_resize(a);
+ }
bool use_qsbr = is_resize && _PyObject_GC_IS_SHARED(a);
#else
bool use_qsbr = false;
@@ -3069,6 +3088,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int
reverse)
Py_XDECREF(final_ob_item[i]);
}
#ifdef Py_GIL_DISABLED
+ ensure_shared_on_resize(self);
bool use_qsbr = _PyObject_GC_IS_SHARED(self);
#else
bool use_qsbr = false;
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]