Bug description:
Follows from #153852 for data race on plain read of cnt in repr
itertoolsmodule.c: count.repr plain-reads cnt while count_next writes it with an atomic CAS — the writer was hardened, the reader missed
import itertools
import threading
STOP = False
def advance(it):
while not STOP:
next(it)
def read_repr(it):
while not STOP:
repr(it)
def main():
global STOP
it = itertools.count()
threads = [threading.Thread(target=advance, args=(it,)) for _ in range(2)]
threads += [threading.Thread(target=read_repr, args=(it,)) for _ in range(4)]
for t in threads:
t.start()
# Let the race run briefly; TSan reports on the first conflicting pair.
threading.Event().wait(2.0)
STOP = True
for t in threads:
t.join()
print("done (no race detected)")
if __name__ == "__main__":
main()
PYTHON_GIL=0 ./python.exe repro_tsan_0006_count.py
SUMMARY: ThreadSanitizer: data race itertoolsmodule.c:3680 in count_repr
==================
done (no race detected)
ThreadSanitizer: reported 2 warnings
[1] 55630 abort PYTHON_GIL=0 ./python.exe repro_tsan_0006_count.py
CPython versions tested on:
CPython main branch
Operating systems tested on:
Macos 26.3.2
Linked PRs
Reactions are currently unavailable
Bug description:
Follows from #153852 for data race on plain read of cnt in repr
import itertools import threading STOP = False def advance(it): while not STOP: next(it) def read_repr(it): while not STOP: repr(it) def main(): global STOP it = itertools.count() threads = [threading.Thread(target=advance, args=(it,)) for _ in range(2)] threads += [threading.Thread(target=read_repr, args=(it,)) for _ in range(4)] for t in threads: t.start() # Let the race run briefly; TSan reports on the first conflicting pair. threading.Event().wait(2.0) STOP = True for t in threads: t.join() print("done (no race detected)") if __name__ == "__main__": main()CPython versions tested on:
CPython main branch
Operating systems tested on:
Macos 26.3.2
Linked PRs