Skip to content

Commit 8da3367

Browse files
[3.11] gh-110167: Fix test_socket deadlock in doCleanups() (GH-110416) (#110424)
gh-110167: Fix test_socket deadlock in doCleanups() (GH-110416) Fix a deadlock in test_socket when server fails with a timeout but the client is still running in its thread. Don't hold a lock to call cleanup functions in doCleanups(). One of the cleanup function waits until the client completes, whereas the client could deadlock if it called addCleanup() in such situation. doCleanups() is called when the server completed, but the client can still be running in its thread especially if the server failed with a timeout. Don't put a lock on doCleanups() to prevent deadlock between addCleanup() called in the client and doCleanups() waiting for self.done.wait of ThreadableTest._setUp(). (cherry picked from commit 318f5df) Co-authored-by: Victor Stinner <[email protected]>
1 parent 8394368 commit 8da3367

File tree

2 files changed

+12
-5
lines changed

2 files changed

+12
-5
lines changed

Lib/test/test_socket.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,13 @@ def setUp(self):
204204
class ThreadSafeCleanupTestCase:
205205
"""Subclass of unittest.TestCase with thread-safe cleanup methods.
206206
207-
This subclass protects the addCleanup() and doCleanups() methods
208-
with a recursive lock.
207+
This subclass protects the addCleanup() method with a recursive lock.
208+
209+
doCleanups() is called when the server completed, but the client can still
210+
be running in its thread especially if the server failed with a timeout.
211+
Don't put a lock on doCleanups() to prevent deadlock between addCleanup()
212+
called in the client and doCleanups() waiting for self.done.wait of
213+
ThreadableTest._setUp() (gh-110167)
209214
"""
210215

211216
def __init__(self, *args, **kwargs):
@@ -216,9 +221,6 @@ def addCleanup(self, *args, **kwargs):
216221
with self._cleanup_lock:
217222
return super().addCleanup(*args, **kwargs)
218223

219-
def doCleanups(self, *args, **kwargs):
220-
with self._cleanup_lock:
221-
return super().doCleanups(*args, **kwargs)
222224

223225
class SocketCANTest(unittest.TestCase):
224226

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Fix a deadlock in test_socket when server fails with a timeout but the
2+
client is still running in its thread. Don't hold a lock to call cleanup
3+
functions in doCleanups(). One of the cleanup function waits until the
4+
client completes, whereas the client could deadlock if it called
5+
addCleanup() in such situation. Patch by Victor Stinner.

0 commit comments

Comments
 (0)