diff --git a/Include/internal/pycore_critical_section.h b/Include/internal/pycore_critical_section.h index 7bebcdb67c7169..b3d15cc1b856b9 100644 --- a/Include/internal/pycore_critical_section.h +++ b/Include/internal/pycore_critical_section.h @@ -98,6 +98,8 @@ extern "C" { # define Py_END_CRITICAL_SECTION() \ _PyCriticalSection_End(&_cs); \ } +# define Py_EXIT_CRITICAL_SECTION() \ + _PyCriticalSection_End(&_cs); # define Py_BEGIN_CRITICAL_SECTION2(a, b) \ { \ @@ -156,6 +158,7 @@ extern "C" { # define Py_BEGIN_CRITICAL_SECTION(op) # define Py_END_CRITICAL_SECTION() # define Py_BEGIN_CRITICAL_SECTION2(a, b) +# define Py_EXIT_CRITICAL_SECTION() # define Py_END_CRITICAL_SECTION2() # define Py_BEGIN_CRITICAL_SECTION_SEQUENCE_FAST(original) # define Py_END_CRITICAL_SECTION_SEQUENCE_FAST() diff --git a/Misc/NEWS.d/next/Core and Builtins/2024-06-16-22-42-47.gh-issue-120608._-YtWX.rst b/Misc/NEWS.d/next/Core and Builtins/2024-06-16-22-42-47.gh-issue-120608._-YtWX.rst new file mode 100644 index 00000000000000..76e018eeefbcfa --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2024-06-16-22-42-47.gh-issue-120608._-YtWX.rst @@ -0,0 +1 @@ +Make :func:`reversed` thread-safe. diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 556666779d8522..668166c3a2dd20 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -2,6 +2,7 @@ #include "Python.h" #include "pycore_call.h" // _PyObject_CallNoArgs() +#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION() #include "pycore_long.h" // _PyLong_GetOne() #include "pycore_modsupport.h" // _PyArg_NoKwnames() #include "pycore_object.h" // _PyObject_GC_TRACK() @@ -431,16 +432,20 @@ reversed_next(reversedobject *ro) PyObject *item; Py_ssize_t index = ro->index; + Py_BEGIN_CRITICAL_SECTION(ro); if (index >= 0) { item = PySequence_GetItem(ro->seq, index); if (item != NULL) { ro->index--; + Py_EXIT_CRITICAL_SECTION(); return item; } if (PyErr_ExceptionMatches(PyExc_IndexError) || PyErr_ExceptionMatches(PyExc_StopIteration)) PyErr_Clear(); } + Py_END_CRITICAL_SECTION(); + ro->index = -1; Py_CLEAR(ro->seq); return NULL;