commit:     3b1234ba69a31709cd5aec1ae070901e3a28bb7c
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed Nov  1 05:07:32 2023 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Thu Nov  2 14:56:37 2023 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=3b1234ba

testAsyncFunctionStdin: multiprocessing spawn compat

For compatibility with the multiprocessing spawn start
method, we delay restoration of the stdin file descriptor,
since this file descriptor is sent to the subprocess
asynchronously.

Signed-off-by: Zac Medico <zmedico <AT> gentoo.org>
Bug: https://bugs.gentoo.org/916601

 lib/portage/tests/process/test_AsyncFunction.py | 30 +++++++++++++++++++------
 1 file changed, 23 insertions(+), 7 deletions(-)

diff --git a/lib/portage/tests/process/test_AsyncFunction.py 
b/lib/portage/tests/process/test_AsyncFunction.py
index d02a3395c1..1faf8f49f7 100644
--- a/lib/portage/tests/process/test_AsyncFunction.py
+++ b/lib/portage/tests/process/test_AsyncFunction.py
@@ -42,21 +42,37 @@ class AsyncFunctionTestCase(TestCase):
                 ),
             )
             reader.start()
+            # For compatibility with the multiprocessing spawn start
+            # method, we delay restoration of the stdin file descriptor,
+            # since this file descriptor is sent to the subprocess
+            # asynchronously.
+            _set_nonblocking(pw.fileno())
+            with open(pw.fileno(), mode="wb", buffering=0, closefd=False) as 
pipe_write:
+                await _writer(pipe_write, test_string.encode("utf_8"))
+            pw.close()
+            self.assertEqual((await reader.async_wait()), os.EX_OK)
+            self.assertEqual(reader.result, test_string)
         finally:
             os.dup2(stdin_backup, portage._get_stdin().fileno())
             os.close(stdin_backup)
 
-        _set_nonblocking(pw.fileno())
-        with open(pw.fileno(), mode="wb", buffering=0, closefd=False) as 
pipe_write:
-            await _writer(pipe_write, test_string.encode("utf_8"))
-        pw.close()
-        self.assertEqual((await reader.async_wait()), os.EX_OK)
-        self.assertEqual(reader.result, test_string)
-
     def testAsyncFunctionStdin(self):
         loop = asyncio._wrap_loop()
         loop.run_until_complete(self._testAsyncFunctionStdin(loop=loop))
 
+    def testAsyncFunctionStdinSpawn(self):
+        orig_start_method = multiprocessing.get_start_method()
+        if orig_start_method == "spawn":
+            self.skipTest("multiprocessing start method is already spawn")
+        # NOTE: An attempt was made to use multiprocessing.get_context("spawn")
+        # here, but it caused the python process to terminate unexpectedly
+        # during a send_handle call.
+        multiprocessing.set_start_method("spawn", force=True)
+        try:
+            self.testAsyncFunctionStdin()
+        finally:
+            multiprocessing.set_start_method(orig_start_method, force=True)
+
     @staticmethod
     def _test_getpid_fork(preexec_fn=None):
         """

Reply via email to