Skip to content

Crash when calling textiowrapper_iternext and writing to a text file simultaneously in ft build #134908

Closed
@duaneg

Description

@duaneg

Running this script under free-threading build:

import os
import tempfile
import threading

N=2
COUNT=100

def writer(file, barrier):
    barrier.wait()
    for _ in range(COUNT):
        f.write("x")

def reader(file, stopping):
    while not stopping.is_set():
        for line in file:
            assert line == ""

stopping = threading.Event()
with tempfile.NamedTemporaryFile("w+") as f:
    reader = threading.Thread(target=reader, args=(f, stopping))
    reader.start()

    barrier = threading.Barrier(N)
    writers = [threading.Thread(target=writer, args=(f, barrier))
               for _ in range(N)]
    for t in writers:
        t.start()
    for t in writers:
        t.join()
    stopping.set()
    reader.join()

    f.flush()
    assert(os.stat(f.name).st_size == COUNT * N)

...results in a crash:

python: ./Modules/_io/textio.c:1751: _io_TextIOWrapper_write_impl: Assertion `self->pending_bytes_count == 0' failed.
Aborted (core dumped)

The textiowrapper_iternext method is not protected by a critical section and calls _textiowrapper_readline, which calls _textiowrapper_writeflush, which relies on the GIL or critical section to synchronise access to its internal data. In a free-threading build this means iterating over lines in a text file is not thread-safe and can crash if it races with writes or other operations.

It looks like all other entry points that could call _textiowrapper_writeflush are protected by the critical section, so the easiest fix is probably to just likewise protect textiowrapper_iternext.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)topic-free-threadingtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions