mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted
while it is holding a lock to a buffered I/O object, and the main thread tries to use the same I/O object (typically stdout or stderr). A fatal error is emitted instead.
This commit is contained in:
parent
f3b990e48c
commit
25f85d4bd5
5 changed files with 94 additions and 15 deletions
|
@ -35,7 +35,7 @@ import weakref
|
|||
from collections import deque, UserList
|
||||
from itertools import cycle, count
|
||||
from test import support
|
||||
from test.script_helper import assert_python_ok
|
||||
from test.script_helper import assert_python_ok, run_python_until_end
|
||||
|
||||
import codecs
|
||||
import io # C implementation of io
|
||||
|
@ -3350,6 +3350,49 @@ class CMiscIOTest(MiscIOTest):
|
|||
b = bytearray(2)
|
||||
self.assertRaises(ValueError, bufio.readinto, b)
|
||||
|
||||
@unittest.skipUnless(threading, 'Threading required for this test.')
|
||||
def check_daemon_threads_shutdown_deadlock(self, stream_name):
|
||||
# Issue #23309: deadlocks at shutdown should be avoided when a
|
||||
# daemon thread and the main thread both write to a file.
|
||||
code = """if 1:
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
|
||||
file = sys.{stream_name}
|
||||
|
||||
def run():
|
||||
while True:
|
||||
file.write('.')
|
||||
file.flush()
|
||||
|
||||
thread = threading.Thread(target=run)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
time.sleep(0.5)
|
||||
file.write('!')
|
||||
file.flush()
|
||||
""".format_map(locals())
|
||||
res, _ = run_python_until_end("-c", code)
|
||||
err = res.err.decode()
|
||||
if res.rc != 0:
|
||||
# Failure: should be a fatal error
|
||||
self.assertIn("Fatal Python error: could not acquire lock "
|
||||
"for <_io.BufferedWriter name='<{stream_name}>'> "
|
||||
"at interpreter shutdown, possibly due to "
|
||||
"daemon threads".format_map(locals()),
|
||||
err)
|
||||
else:
|
||||
self.assertFalse(err.strip('.!'))
|
||||
|
||||
def test_daemon_threads_shutdown_stdout_deadlock(self):
|
||||
self.check_daemon_threads_shutdown_deadlock('stdout')
|
||||
|
||||
def test_daemon_threads_shutdown_stderr_deadlock(self):
|
||||
self.check_daemon_threads_shutdown_deadlock('stderr')
|
||||
|
||||
|
||||
class PyMiscIOTest(MiscIOTest):
|
||||
io = pyio
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue