]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-108973: Fix asyncio SubprocessProtocol doc (#109431) (#109610)
authorVictor Stinner <vstinner@python.org>
Wed, 20 Sep 2023 14:15:08 +0000 (16:15 +0200)
committerGitHub <noreply@github.com>
Wed, 20 Sep 2023 14:15:08 +0000 (14:15 +0000)
gh-108973: Fix asyncio SubprocessProtocol doc (#109431)

SubprocessProtocol process_exited() method can be called before
pipe_data_received() and pipe_connection_lost() methods. Document it
and adapt the example in the doc.

Co-authored-by: Davide Rizzo <sorcio@gmail.com>
(cherry picked from commit ced6924630037f1e5b3d1dbef2b600152fb07fbb)

Doc/library/asyncio-llapi-index.rst
Doc/library/asyncio-protocol.rst

index 9ce48a24444e66d0387cbc73bf1e01b73e54f09c..67136ba69ec875b69c01569d175a52a8ac99cc37 100644 (file)
@@ -484,19 +484,19 @@ Protocol classes can implement the following **callback methods**:
     :widths: 50 50
     :class: full-width-table
 
-    * - ``callback`` :meth:`pipe_data_received()
-        <SubprocessProtocol.pipe_data_received>`
+    * - ``callback`` :meth:`~SubprocessProtocol.pipe_data_received`
       - Called when the child process writes data into its
         *stdout* or *stderr* pipe.
 
-    * - ``callback`` :meth:`pipe_connection_lost()
-        <SubprocessProtocol.pipe_connection_lost>`
+    * - ``callback`` :meth:`~SubprocessProtocol.pipe_connection_lost`
       - Called when one of the pipes communicating with
         the child process is closed.
 
     * - ``callback`` :meth:`process_exited()
         <SubprocessProtocol.process_exited>`
-      - Called when the child process has exited.
+      - Called when the child process has exited. It can be called before
+        :meth:`~SubprocessProtocol.pipe_data_received` and
+        :meth:`~SubprocessProtocol.pipe_connection_lost` methods.
 
 
 Event Loop Policies
index 7bc906eaafc1f26f228b80c81f0a9ceff48ada4d..48fa02937b5237f7b655f99cbe81e1e127f84634 100644 (file)
@@ -708,6 +708,9 @@ factories passed to the :meth:`loop.subprocess_exec` and
 
    Called when the child process has exited.
 
+   It can be called before :meth:`~SubprocessProtocol.pipe_data_received` and
+   :meth:`~SubprocessProtocol.pipe_connection_lost` methods.
+
 
 Examples
 ========
@@ -1003,12 +1006,26 @@ The subprocess is created by the :meth:`loop.subprocess_exec` method::
         def __init__(self, exit_future):
             self.exit_future = exit_future
             self.output = bytearray()
+            self.pipe_closed = False
+            self.exited = False
+
+        def pipe_connection_lost(self, fd, exc):
+            self.pipe_closed = True
+            self.check_for_exit()
 
         def pipe_data_received(self, fd, data):
             self.output.extend(data)
 
         def process_exited(self):
-            self.exit_future.set_result(True)
+            self.exited = True
+            # process_exited() method can be called before
+            # pipe_connection_lost() method: wait until both methods are
+            # called.
+            self.check_for_exit()
+
+        def check_for_exit(self):
+            if self.pipe_closed and self.exited:
+                self.exit_future.set_result(True)
 
     async def get_date():
         # Get a reference to the event loop as we plan to use