gh-112087: Make PyList_{Append,Size,GetSlice} to be thread-safe (gh-114651)

This commit is contained in:
Donghee Na 2024-02-01 08:58:08 +09:00 committed by GitHub
parent 1836f674c0
commit 7b9d406729
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 21 additions and 8 deletions

View File

@ -24,12 +24,13 @@ extern void _PyList_Fini(_PyFreeListState *);
extern int extern int
_PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem); _PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem);
// In free-threaded build: self should be locked by the caller, if it should be thread-safe.
static inline int static inline int
_PyList_AppendTakeRef(PyListObject *self, PyObject *newitem) _PyList_AppendTakeRef(PyListObject *self, PyObject *newitem)
{ {
assert(self != NULL && newitem != NULL); assert(self != NULL && newitem != NULL);
assert(PyList_Check(self)); assert(PyList_Check(self));
Py_ssize_t len = PyList_GET_SIZE(self); Py_ssize_t len = Py_SIZE(self);
Py_ssize_t allocated = self->allocated; Py_ssize_t allocated = self->allocated;
assert((size_t)len + 1 < PY_SSIZE_T_MAX); assert((size_t)len + 1 < PY_SSIZE_T_MAX);
if (allocated > len) { if (allocated > len) {

View File

@ -428,7 +428,11 @@ static inline void Py_SET_TYPE(PyObject *ob, PyTypeObject *type) {
static inline void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) { static inline void Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) {
assert(ob->ob_base.ob_type != &PyLong_Type); assert(ob->ob_base.ob_type != &PyLong_Type);
assert(ob->ob_base.ob_type != &PyBool_Type); assert(ob->ob_base.ob_type != &PyBool_Type);
#ifdef Py_GIL_DISABLED
_Py_atomic_store_ssize_relaxed(&ob->ob_size, size);
#else
ob->ob_size = size; ob->ob_size = size;
#endif
} }
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000 #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
# define Py_SET_SIZE(ob, size) Py_SET_SIZE(_PyVarObject_CAST(ob), (size)) # define Py_SET_SIZE(ob, size) Py_SET_SIZE(_PyVarObject_CAST(ob), (size))

View File

@ -30,7 +30,6 @@ get_list_state(void)
} }
#endif #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
@ -221,8 +220,9 @@ PyList_Size(PyObject *op)
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return -1; return -1;
} }
else else {
return Py_SIZE(op); return PyList_GET_SIZE(op);
}
} }
static inline int static inline int
@ -328,7 +328,7 @@ PyList_Insert(PyObject *op, Py_ssize_t where, PyObject *newitem)
int int
_PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem) _PyList_AppendTakeRefListResize(PyListObject *self, PyObject *newitem)
{ {
Py_ssize_t len = PyList_GET_SIZE(self); Py_ssize_t len = Py_SIZE(self);
assert(self->allocated == -1 || self->allocated == len); assert(self->allocated == -1 || self->allocated == len);
if (list_resize(self, len + 1) < 0) { if (list_resize(self, len + 1) < 0) {
Py_DECREF(newitem); Py_DECREF(newitem);
@ -342,7 +342,11 @@ int
PyList_Append(PyObject *op, PyObject *newitem) PyList_Append(PyObject *op, PyObject *newitem)
{ {
if (PyList_Check(op) && (newitem != NULL)) { if (PyList_Check(op) && (newitem != NULL)) {
return _PyList_AppendTakeRef((PyListObject *)op, Py_NewRef(newitem)); int ret;
Py_BEGIN_CRITICAL_SECTION(op);
ret = _PyList_AppendTakeRef((PyListObject *)op, Py_NewRef(newitem));
Py_END_CRITICAL_SECTION();
return ret;
} }
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return -1; return -1;
@ -473,7 +477,7 @@ static PyObject *
list_item(PyObject *aa, Py_ssize_t i) list_item(PyObject *aa, Py_ssize_t i)
{ {
PyListObject *a = (PyListObject *)aa; PyListObject *a = (PyListObject *)aa;
if (!valid_index(i, Py_SIZE(a))) { if (!valid_index(i, PyList_GET_SIZE(a))) {
PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err)); PyErr_SetObject(PyExc_IndexError, &_Py_STR(list_err));
return NULL; return NULL;
} }
@ -511,6 +515,8 @@ PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
PyErr_BadInternalCall(); PyErr_BadInternalCall();
return NULL; return NULL;
} }
PyObject *ret;
Py_BEGIN_CRITICAL_SECTION(a);
if (ilow < 0) { if (ilow < 0) {
ilow = 0; ilow = 0;
} }
@ -523,7 +529,9 @@ PyList_GetSlice(PyObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
else if (ihigh > Py_SIZE(a)) { else if (ihigh > Py_SIZE(a)) {
ihigh = Py_SIZE(a); ihigh = Py_SIZE(a);
} }
return list_slice((PyListObject *)a, ilow, ihigh); ret = list_slice((PyListObject *)a, ilow, ihigh);
Py_END_CRITICAL_SECTION();
return ret;
} }
static PyObject * static PyObject *