import sys
import pickle
import gc
+import threading
+
from test import support
+from test.support import threading_helper
class G:
'Sequence using __getitem__'
(sys.maxsize+3,'c')]
+@threading_helper.requires_working_threading()
+class TestThreadSafety(EnumerateStartTestCase):
+ def test_thread_safety_while_iterating(self):
+ # gh-153932: calling reduce while iterating should pass with TSAN
+
+ en = enumerate(range(10_000))
+ stop = threading.Event()
+
+ def advance():
+ for _ in en:
+ pass
+ stop.set()
+
+ def read():
+ while not stop.is_set():
+ en.__reduce__()
+
+ threads = [threading.Thread(target=advance), threading.Thread(target=read)]
+
+ with threading_helper.start_threads(threads):
+ pass
+
+
if __name__ == "__main__":
unittest.main()
enumobject *en = _enumobject_CAST(op);
PyObject *result;
Py_BEGIN_CRITICAL_SECTION(en);
- if (en->en_longindex != NULL)
+ if (en->en_longindex != NULL) {
result = Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex);
- else
- result = Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
+ }
+ else {
+ Py_ssize_t en_index = FT_ATOMIC_LOAD_SSIZE_RELAXED(en->en_index);
+ result = Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en_index);
+ }
Py_END_CRITICAL_SECTION();
return result;
}