This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: threading issue in __builtins__.print
Type: behavior Stage:
Components: IO Versions: Python 3.1
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: pitrou Nosy List: amaury.forgeotdarc, nullnil, pitrou
Priority: normal Keywords: needs review, patch

Created on 2009-08-21 07:28 by nullnil, last changed 2022-04-11 14:56 by admin. This issue is now closed.

File name Uploaded Description Edit
textiowrapper_write.patch amaury.forgeotdarc, 2009-08-21 12:34
Messages (4)
msg91807 - (view) Author: Jackson Yang (nullnil) Date: 2009-08-21 07:28
# 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):
        self.ord = ord
    def run(self):
        print('Hello, world!', self.ord)
threads = tuple(map(Test, range(8)))
tuple(map(lambda thread: thread.start(), threads))
tuple(map(lambda thread: thread.join(), threads))

# 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.
State this as The Expected Behavior, document it and ask the user to
write something such as critical section.
msg91823 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2009-08-21 12:34
The TextIOWrapper class is not thread-safe, because it calls [the
equivalent of] self.buffer.write(self.pending_bytes) before clearing
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.)
msg92061 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2009-08-29 11:22
The patch looks ok to me.
It should be noted that TextIOWrapper was not designed to be thread-safe
at all (neither the Python nor the C version); but admittedly it is more
common to write() than to read() from multiple threads, so fixing this
particular case makes sense.
msg92073 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2009-08-29 23:26
fixed with r74581, r74582 and r74583 (in: trunk, py3k and release31-maint)
Date User Action Args
2022-04-11 14:56:52adminsetgithub: 50999
2009-08-29 23:26:08amaury.forgeotdarcsetstatus: open -> closed
resolution: fixed
messages: + msg92073
2009-08-29 11:22:13pitrousetmessages: + msg92061
2009-08-21 12:34:58amaury.forgeotdarcsetfiles: + textiowrapper_write.patch

nosy: + amaury.forgeotdarc, pitrou
messages: + msg91823

assignee: pitrou
keywords: + needs review, patch
2009-08-21 07:28:27nullnilcreate