Simple racing class attribute read-write crashes on free-threaded builds
Crash report
What happened?
The following segfaults:
from multiprocessing.dummy import Pool NTHREADS = 6 class A: attr = 1 BOTTOM = 0 TOP = 1000 ITERS = 100 def read(id0): for _ in range(ITERS): for _ in range(BOTTOM, TOP): A.attr # print(A.attr) def write(id0): for _ in range(ITERS): for _ in range(BOTTOM, TOP): # Make _PyType_Lookup cache hot first A.attr A.attr x = A.attr x += 1 A.attr = x # print(f"WRITTEN {x}\n") def main(): with Pool(NTHREADS) as pool: pool.apply_async(read, (1,)) pool.apply_async(write, (1,)) pool.close() pool.join() main() print("done")
The first issue is that we have assert(_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)); in typeobject.c, which may not be true as another thread can modify the attribute in the meantime. We should remove that assertion.
The next issue, which I have not yet been able to solve, is that the attribute evaporates midway in _Py_type_getattro_impl. This is likely caused by a decref of another thread. So far I've tried changing _PyType_Lookup and find_name_in_mro to return strong references, but they don't seem to solve it for some reason.
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response
Output from running 'python -VV' on the command line:
No response