Skip to content

Simple racing class attribute read-write crashes on free-threaded builds #118362

@Fidget-Spinner

Description

@Fidget-Spinner

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

Linked PRs

Metadata

Metadata

Assignees

Labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions