gh-127536: Add missing locks in listobject.c (GH-127580)
We were missing locks around some list operations in the free threading build.
This commit is contained in:
parent
51cfa569e3
commit
e51da64ac3
@ -0,0 +1,2 @@
|
|||||||
|
Add missing locks around some list assignment operations in the free
|
||||||
|
threading build.
|
@ -3,6 +3,7 @@
|
|||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||||
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
|
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
|
||||||
|
#include "pycore_critical_section.h" // _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED()
|
||||||
#include "pycore_dict.h" // _PyDictViewObject
|
#include "pycore_dict.h" // _PyDictViewObject
|
||||||
#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP()
|
#include "pycore_freelist.h" // _Py_FREELIST_FREE(), _Py_FREELIST_POP()
|
||||||
#include "pycore_pyatomic_ft_wrappers.h"
|
#include "pycore_pyatomic_ft_wrappers.h"
|
||||||
@ -72,6 +73,11 @@ static void
|
|||||||
ensure_shared_on_resize(PyListObject *self)
|
ensure_shared_on_resize(PyListObject *self)
|
||||||
{
|
{
|
||||||
#ifdef Py_GIL_DISABLED
|
#ifdef Py_GIL_DISABLED
|
||||||
|
// We can't use _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED here because
|
||||||
|
// the `CALL_LIST_APPEND` bytecode handler may lock the list without
|
||||||
|
// a critical section.
|
||||||
|
assert(Py_REFCNT(self) == 1 || PyMutex_IsLocked(&_PyObject_CAST(self)->ob_mutex));
|
||||||
|
|
||||||
// Ensure that the list array is freed using QSBR if we are not the
|
// Ensure that the list array is freed using QSBR if we are not the
|
||||||
// owning thread.
|
// owning thread.
|
||||||
if (!_Py_IsOwnedByCurrentThread((PyObject *)self) &&
|
if (!_Py_IsOwnedByCurrentThread((PyObject *)self) &&
|
||||||
@ -957,10 +963,12 @@ list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v)
|
|||||||
Py_ssize_t n = PyList_GET_SIZE(a);
|
Py_ssize_t n = PyList_GET_SIZE(a);
|
||||||
PyObject *copy = list_slice_lock_held(a, 0, n);
|
PyObject *copy = list_slice_lock_held(a, 0, n);
|
||||||
if (copy == NULL) {
|
if (copy == NULL) {
|
||||||
return -1;
|
ret = -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = list_ass_slice_lock_held(a, ilow, ihigh, copy);
|
||||||
|
Py_DECREF(copy);
|
||||||
}
|
}
|
||||||
ret = list_ass_slice_lock_held(a, ilow, ihigh, copy);
|
|
||||||
Py_DECREF(copy);
|
|
||||||
Py_END_CRITICAL_SECTION();
|
Py_END_CRITICAL_SECTION();
|
||||||
}
|
}
|
||||||
else if (v != NULL && PyList_CheckExact(v)) {
|
else if (v != NULL && PyList_CheckExact(v)) {
|
||||||
@ -1437,7 +1445,9 @@ PyList_Clear(PyObject *self)
|
|||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
list_clear((PyListObject*)self);
|
list_clear((PyListObject*)self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3410,7 +3420,9 @@ list___init___impl(PyListObject *self, PyObject *iterable)
|
|||||||
|
|
||||||
/* Empty previous contents */
|
/* Empty previous contents */
|
||||||
if (self->ob_item != NULL) {
|
if (self->ob_item != NULL) {
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
list_clear(self);
|
list_clear(self);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
}
|
}
|
||||||
if (iterable != NULL) {
|
if (iterable != NULL) {
|
||||||
if (_list_extend(self, iterable) < 0) {
|
if (_list_extend(self, iterable) < 0) {
|
||||||
@ -3583,8 +3595,10 @@ adjust_slice_indexes(PyListObject *lst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value)
|
list_ass_subscript_lock_held(PyObject *_self, PyObject *item, PyObject *value)
|
||||||
{
|
{
|
||||||
|
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(_self);
|
||||||
|
|
||||||
PyListObject *self = (PyListObject *)_self;
|
PyListObject *self = (PyListObject *)_self;
|
||||||
if (_PyIndex_Check(item)) {
|
if (_PyIndex_Check(item)) {
|
||||||
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
|
||||||
@ -3592,7 +3606,7 @@ list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value)
|
|||||||
return -1;
|
return -1;
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
i += PyList_GET_SIZE(self);
|
i += PyList_GET_SIZE(self);
|
||||||
return list_ass_item((PyObject *)self, i, value);
|
return list_ass_item_lock_held(self, i, value);
|
||||||
}
|
}
|
||||||
else if (PySlice_Check(item)) {
|
else if (PySlice_Check(item)) {
|
||||||
Py_ssize_t start, stop, step;
|
Py_ssize_t start, stop, step;
|
||||||
@ -3612,7 +3626,7 @@ list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value)
|
|||||||
step);
|
step);
|
||||||
|
|
||||||
if (step == 1)
|
if (step == 1)
|
||||||
return list_ass_slice(self, start, stop, value);
|
return list_ass_slice_lock_held(self, start, stop, value);
|
||||||
|
|
||||||
if (slicelength <= 0)
|
if (slicelength <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -3678,10 +3692,8 @@ list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value)
|
|||||||
|
|
||||||
/* protect against a[::-1] = a */
|
/* protect against a[::-1] = a */
|
||||||
if (self == (PyListObject*)value) {
|
if (self == (PyListObject*)value) {
|
||||||
Py_BEGIN_CRITICAL_SECTION(value);
|
seq = list_slice_lock_held((PyListObject *)value, 0,
|
||||||
seq = list_slice_lock_held((PyListObject*)value, 0,
|
|
||||||
Py_SIZE(value));
|
Py_SIZE(value));
|
||||||
Py_END_CRITICAL_SECTION();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
seq = PySequence_Fast(value,
|
seq = PySequence_Fast(value,
|
||||||
@ -3695,7 +3707,7 @@ list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value)
|
|||||||
step);
|
step);
|
||||||
|
|
||||||
if (step == 1) {
|
if (step == 1) {
|
||||||
int res = list_ass_slice(self, start, stop, seq);
|
int res = list_ass_slice_lock_held(self, start, stop, seq);
|
||||||
Py_DECREF(seq);
|
Py_DECREF(seq);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -3751,6 +3763,24 @@ list_ass_subscript(PyObject* _self, PyObject* item, PyObject* value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
list_ass_subscript(PyObject *self, PyObject *item, PyObject *value)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
#ifdef Py_GIL_DISABLED
|
||||||
|
if (PySlice_Check(item) && value != NULL && PyList_CheckExact(value)) {
|
||||||
|
Py_BEGIN_CRITICAL_SECTION2(self, value);
|
||||||
|
res = list_ass_subscript_lock_held(self, item, value);
|
||||||
|
Py_END_CRITICAL_SECTION2();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Py_BEGIN_CRITICAL_SECTION(self);
|
||||||
|
res = list_ass_subscript_lock_held(self, item, value);
|
||||||
|
Py_END_CRITICAL_SECTION();
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static PyMappingMethods list_as_mapping = {
|
static PyMappingMethods list_as_mapping = {
|
||||||
list_length,
|
list_length,
|
||||||
list_subscript,
|
list_subscript,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user