summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-10-27 23:36:24 (GMT)
committerGitHub <noreply@github.com>2023-10-27 23:36:24 (GMT)
commit1a01ca44d61d6d90be159771576d6868515399dd (patch)
treea15a2102144d310d1d265bad9eb23f79797f5323 /Lib
parente84b06c05a90c2f32a8e904f0a43ccc8c1cc88e3 (diff)
downloadcpython-1a01ca44d61d6d90be159771576d6868515399dd.zip
cpython-1a01ca44d61d6d90be159771576d6868515399dd.tar.gz
cpython-1a01ca44d61d6d90be159771576d6868515399dd.tar.bz2
[3.11] gh-110205: Fix asyncio ThreadedChildWatcher._join_threads() (GH-110884) (#111413)
- `ThreadedChildWatcher.close()` is now *officially* a no-op; `_join_threads()` never did anything. - Threads created by that class are now named `asyncio-waitpid-NNN`. - `test.test_asyncio.utils.TestCase.close_loop()` now waits for the child watcher's threads, but not forever; if a thread hangs, it raises `RuntimeError`. (cherry picked from commit c3bb10c9303503e7b55a7bdf9acfa6b3bcb699c6) Co-authored-by: Guido van Rossum <guido@python.org>
Diffstat (limited to 'Lib')
-rw-r--r--Lib/asyncio/unix_events.py11
-rw-r--r--Lib/test/test_asyncio/utils.py11
2 files changed, 10 insertions, 12 deletions
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
index 0d4ba72..77d2670 100644
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -1363,14 +1363,7 @@ class ThreadedChildWatcher(AbstractChildWatcher):
return True
def close(self):
- self._join_threads()
-
- def _join_threads(self):
- """Internal: Join all non-daemon threads"""
- threads = [thread for thread in list(self._threads.values())
- if thread.is_alive() and not thread.daemon]
- for thread in threads:
- thread.join()
+ pass
def __enter__(self):
return self
@@ -1389,7 +1382,7 @@ class ThreadedChildWatcher(AbstractChildWatcher):
def add_child_handler(self, pid, callback, *args):
loop = events.get_running_loop()
thread = threading.Thread(target=self._do_waitpid,
- name=f"waitpid-{next(self._pid_counter)}",
+ name=f"asyncio-waitpid-{next(self._pid_counter)}",
args=(loop, pid, callback, args),
daemon=True)
self._threads[pid] = thread
diff --git a/Lib/test/test_asyncio/utils.py b/Lib/test/test_asyncio/utils.py
index 7940855..045e385 100644
--- a/Lib/test/test_asyncio/utils.py
+++ b/Lib/test/test_asyncio/utils.py
@@ -548,6 +548,7 @@ class TestCase(unittest.TestCase):
else:
loop._default_executor.shutdown(wait=True)
loop.close()
+
policy = support.maybe_get_event_loop_policy()
if policy is not None:
try:
@@ -557,9 +558,13 @@ class TestCase(unittest.TestCase):
pass
else:
if isinstance(watcher, asyncio.ThreadedChildWatcher):
- threads = list(watcher._threads.values())
- for thread in threads:
- thread.join()
+ # Wait for subprocess to finish, but not forever
+ for thread in list(watcher._threads.values()):
+ thread.join(timeout=support.SHORT_TIMEOUT)
+ if thread.is_alive():
+ raise RuntimeError(f"thread {thread} still alive: "
+ "subprocess still running")
+
def set_event_loop(self, loop, *, cleanup=True):
if loop is None: