Skip to content

Commit 22a9cfd

Browse files
authored
[mypyc] Make list remove and index thread-safe on free-threaded builds (#21614)
The primitives for `list.remove` and `list.index` were missing critical sections.
1 parent 27d7a35 commit 22a9cfd

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

mypyc/lib-rt/list_ops.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,8 @@ PyObject *CPyList_Extend(PyObject *o1, PyObject *o2) {
301301
}
302302

303303
// Return -2 or error, -1 if not found, or index of first match otherwise.
304+
//
305+
// The caller must hold a critical section on the list.
304306
static Py_ssize_t _CPyList_Find(PyObject *list, PyObject *obj) {
305307
Py_ssize_t i;
306308
for (i = 0; i < Py_SIZE(list); i++) {
@@ -320,27 +322,35 @@ static Py_ssize_t _CPyList_Find(PyObject *list, PyObject *obj) {
320322
}
321323

322324
int CPyList_Remove(PyObject *list, PyObject *obj) {
325+
int retval;
326+
Py_BEGIN_CRITICAL_SECTION(list);
323327
Py_ssize_t index = _CPyList_Find(list, obj);
324328
if (index == -2) {
325-
return -1;
326-
}
327-
if (index == -1) {
329+
retval = -1;
330+
} else if (index == -1) {
328331
PyErr_SetString(PyExc_ValueError, "list.remove(x): x not in list");
329-
return -1;
332+
retval = -1;
333+
} else {
334+
retval = PyList_SetSlice(list, index, index + 1, NULL);
330335
}
331-
return PyList_SetSlice(list, index, index + 1, NULL);
336+
Py_END_CRITICAL_SECTION();
337+
return retval;
332338
}
333339

334340
CPyTagged CPyList_Index(PyObject *list, PyObject *obj) {
341+
CPyTagged retval;
342+
Py_BEGIN_CRITICAL_SECTION(list);
335343
Py_ssize_t index = _CPyList_Find(list, obj);
336344
if (index == -2) {
337-
return CPY_INT_TAG;
338-
}
339-
if (index == -1) {
345+
retval = CPY_INT_TAG;
346+
} else if (index == -1) {
340347
PyErr_SetString(PyExc_ValueError, "value is not in list");
341-
return CPY_INT_TAG;
348+
retval = CPY_INT_TAG;
349+
} else {
350+
retval = index << 1;
342351
}
343-
return index << 1;
352+
Py_END_CRITICAL_SECTION();
353+
return retval;
344354
}
345355

346356
PyObject *CPySequence_Sort(PyObject *seq) {

0 commit comments

Comments
 (0)