Bug report
Bug description:
Hi,
We're a research group focused on testing concurrent runtimes. Our work-in-progress prototype found that the current nogil build __str__ can return "{}" (empty dict) instead of the expected "set()" when there is a concurrent clear() operation. The program below shows the wrong behavior:
import threading import sys def t0(b1,s,res): b1.wait() s.clear() def t1(b1,s,res): b1.wait() res.append(s.__str__()) def Test(): s = {17, 18, 'a', 'b', 'c', 'd', 'e'} threads=[] barrier = threading.Barrier(2) res = [] threads.append(threading.Thread(target= t0, args=(barrier, s,res))) threads.append(threading.Thread(target= t1, args=(barrier, s,res))) for i in range(0, len(threads)): threads[i].start() for i in range(0, len(threads)): threads[i].join() if res[0] == "{}": print("found bug: " + res[0]) print("test begin...") for i in range(0,50000): threads = [] if i % 1000 == 0: print(i) for i in range(0,100): threads.append(threading.Thread(target= Test)) for t in threads: t.start() for t in threads: t.join() print("test Done")
Sample output:
test begin...
0
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
found bug: {}
This behavior can be observed quite readily. We tested it on a number of x86_64 and one ARM machine.
@flypoodles and @overlorde are part of the team, adding them so they get notified about further discussion.
CPython versions tested on:
3.14, CPython main branch
Operating systems tested on:
Linux