]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-110205: Fix asyncio ThreadedChildWatcher._join_threads() (GH-110884) (...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 27 Oct 2023 23:36:24 +0000 (01:36 +0200)
committerGitHub <noreply@github.com>
Fri, 27 Oct 2023 23:36:24 +0000 (16:36 -0700)
- `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>
Lib/asyncio/unix_events.py
Lib/test/test_asyncio/utils.py

index 0d4ba72603e675b5467b9ac08af0318eeceb4ba0..77d2670f833fbc3693a0f08cc00157e39af5eafe 100644 (file)
@@ -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
index 7940855b19efed25e836005ad47ca102620a872a..045e385511bbae5bb15a544e266b4752de5a2f28 100644 (file)
@@ -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: