◐ Shell
clean mode source ↗

Issue 6750: threading issue in __builtins__.print

# Bug Description
In a multi-threaded environment, the Win32 Python3000 built-in function
"print" may give the output several times.

# How to Reproduce:
import threading
event = threading.Event()
class Test(threading.Thread):
    def __init__(self, ord):
        super().__init__()
        self.ord = ord
    def run(self):
        event.wait()
        print('Hello, world!', self.ord)
threads = tuple(map(Test, range(8)))
tuple(map(lambda thread: thread.start(), threads))
event.set()
tuple(map(lambda thread: thread.join(), threads))
# EOF

# Problem Observed
[The first run, 0 is doubled]
Hello, world! 0
Hello, world! 0
Hello, world! 1
Hello, world! 2
Hello, world! 3
Hello, world! 4
Hello, world! 5
Hello, world! 6
Hello, world! 7

[the second run, 1 and 7 are doubled]
Hello, world! 1
Hello, world! 1
Hello, world! 2
Hello, world! 3
Hello, world! 4
Hello, world! 5
Hello, world! 6
Hello, world! 7
Hello, world! 7
Hello, world! 0

# Expected Result
Each thread gives ONE AND ONLY ONE output.
OR
State this as The Expected Behavior, document it and ask the user to
write something such as critical section.
The TextIOWrapper class is not thread-safe, because it calls [the
equivalent of] self.buffer.write(self.pending_bytes) before clearing
self.pending_bytes.
Of course the write() function will release the GIL, and another thread
may send the same pending_bytes again.

Patch is attached. Antoine, can you review it?

(_pyio.TextIOWrapper does no buffering.)