From 4d3cbdd630046d4f2773e089146f0955155a4246 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Fri, 1 Apr 2022 10:14:49 +0200 Subject: [PATCH 1/2] bpo-40280: Emscripten fork_exec now fails early Emscripten and WASI don't support processes. Report the problem earlier without compiling dysfunctional C extensions. --- Lib/subprocess.py | 10 ++++++++-- configure | 3 +++ configure.ac | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Lib/subprocess.py b/Lib/subprocess.py index ad08339b25ddc3..b58c5784283902 100644 --- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -96,7 +96,13 @@ "CREATE_NO_WINDOW", "DETACHED_PROCESS", "CREATE_DEFAULT_ERROR_MODE", "CREATE_BREAKAWAY_FROM_JOB"]) else: - import _posixsubprocess + if sys.platform in {"emscripten", "wasi"}: + def _fork_exec(*args, **kwargs): + raise OSError( + errno.ENOTSUP, f"{sys.platform} does not support processes." + ) + else: + from _posixsubprocess import fork_exec as _fork_exec import select import selectors @@ -1777,7 +1783,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds, for dir in os.get_exec_path(env)) fds_to_keep = set(pass_fds) fds_to_keep.add(errpipe_write) - self.pid = _posixsubprocess.fork_exec( + self.pid = _fork_exec( args, executable_list, close_fds, tuple(sorted(map(int, fds_to_keep))), cwd, env_list, diff --git a/configure b/configure index f08a01caafdd5e..a5062d7b815737 100755 --- a/configure +++ b/configure @@ -21772,6 +21772,9 @@ case $ac_sys_system/$ac_sys_emscripten_target in #( py_cv_module__curses_panel=n/a py_cv_module__dbm=n/a py_cv_module__gdbm=n/a + py_cv_module__multiprocessing=n/a + py_cv_module__posixshmem=n/a + py_cv_module__posixsubprocess=n/a py_cv_module__scproxy=n/a py_cv_module__tkinter=n/a py_cv_module__xxsubinterpreters=n/a diff --git a/configure.ac b/configure.ac index bc3d8b87def9c5..84bc9b3ca5cf04 100644 --- a/configure.ac +++ b/configure.ac @@ -6518,6 +6518,9 @@ AS_CASE([$ac_sys_system/$ac_sys_emscripten_target], [_curses_panel], [_dbm], [_gdbm], + [_multiprocessing], + [_posixshmem], + [_posixsubprocess], [_scproxy], [_tkinter], [_xxsubinterpreters], From 957584353067c6b32f11bce82cc64cda71d05f29 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Fri, 1 Apr 2022 11:10:45 +0200 Subject: [PATCH 2/2] Fix mocking --- Lib/test/test_subprocess.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 99a25e279df92c..8603b9888bb984 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1805,7 +1805,7 @@ class PopenNoDestructor(subprocess.Popen): def __del__(self): pass - @mock.patch("subprocess._posixsubprocess.fork_exec") + @mock.patch("subprocess._fork_exec") def test_exception_errpipe_normal(self, fork_exec): """Test error passing done through errpipe_write in the good case""" def proper_error(*args): @@ -1822,7 +1822,7 @@ def proper_error(*args): with self.assertRaises(IsADirectoryError): self.PopenNoDestructor(["non_existent_command"]) - @mock.patch("subprocess._posixsubprocess.fork_exec") + @mock.patch("subprocess._fork_exec") def test_exception_errpipe_bad_data(self, fork_exec): """Test error passing done through errpipe_write where its not in the expected format""" @@ -2112,7 +2112,7 @@ def raise_it(): preexec_fn=raise_it) except subprocess.SubprocessError as e: self.assertTrue( - subprocess._posixsubprocess, + subprocess._fork_exec, "Expected a ValueError from the preexec_fn") except ValueError as e: self.assertIn("coconut", e.args[0]) @@ -2600,11 +2600,11 @@ def prepare(): preexec_fn=prepare) except ValueError as err: # Pure Python implementations keeps the message - self.assertIsNone(subprocess._posixsubprocess) + self.assertIsNone(subprocess._fork_exec) self.assertEqual(str(err), "surrogate:\uDCff") except subprocess.SubprocessError as err: # _posixsubprocess uses a default message - self.assertIsNotNone(subprocess._posixsubprocess) + self.assertIsNotNone(subprocess._fork_exec) self.assertEqual(str(err), "Exception occurred in preexec_fn.") else: self.fail("Expected ValueError or subprocess.SubprocessError")