diff options
author | Gregory P. Smith <greg@krypto.org> | 2022-04-25 23:19:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-25 23:19:39 (GMT) |
commit | cd5726fe674eaff442510eeb6c75628858be9e9f (patch) | |
tree | d311f0b144298e29596d1fb5dcc4629ec9e8647e /Lib/test | |
parent | eddd07f840c9a4ab0ee05ce56d98caac0f072cef (diff) | |
download | cpython-cd5726fe674eaff442510eeb6c75628858be9e9f.zip cpython-cd5726fe674eaff442510eeb6c75628858be9e9f.tar.gz cpython-cd5726fe674eaff442510eeb6c75628858be9e9f.tar.bz2 |
gh-91401: Add a failsafe way to disable vfork. (#91490)
Just in case there is ever an issue with _posixsubprocess's use of
vfork() due to the complexity of using it properly and potential
directions that Linux platforms where it defaults to on could take, this
adds a failsafe so that users can disable its use entirely by setting
a global flag.
No known reason to disable it exists. But it'd be a shame to encounter
one and not be able to use CPython without patching and rebuilding it.
See the linked issue for some discussion on reasoning.
Also documents the existing way to disable posix_spawn.
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_capi.py | 6 | ||||
-rw-r--r-- | Lib/test/test_subprocess.py | 20 |
2 files changed, 21 insertions, 5 deletions
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 5f5d351..1aed9b7 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -140,7 +140,7 @@ class CAPITest(unittest.TestCase): def __len__(self): return 1 self.assertRaises(TypeError, _posixsubprocess.fork_exec, - 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) + 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) # Issue #15736: overflow in _PySequence_BytesToCharpArray() class Z(object): def __len__(self): @@ -148,7 +148,7 @@ class CAPITest(unittest.TestCase): def __getitem__(self, i): return b'x' self.assertRaises(MemoryError, _posixsubprocess.fork_exec, - 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) + 1,Z(),3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) @unittest.skipUnless(_posixsubprocess, '_posixsubprocess required for this test.') def test_subprocess_fork_exec(self): @@ -158,7 +158,7 @@ class CAPITest(unittest.TestCase): # Issue #15738: crash in subprocess_fork_exec() self.assertRaises(TypeError, _posixsubprocess.fork_exec, - Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21) + Z(),[b'1'],3,(1, 2),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22) @unittest.skipIf(MISSING_C_DOCSTRINGS, "Signature information for builtins requires docstrings") diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index 8603b98..99b5947 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1543,6 +1543,22 @@ class ProcessTestCase(BaseTestCase): self.assertIsInstance(subprocess.Popen[bytes], types.GenericAlias) self.assertIsInstance(subprocess.CompletedProcess[str], types.GenericAlias) + @unittest.skipIf(not sysconfig.get_config_var("HAVE_VFORK"), + "vfork() not enabled by configure.") + @mock.patch("subprocess._fork_exec") + def test__use_vfork(self, mock_fork_exec): + self.assertTrue(subprocess._USE_VFORK) # The default value regardless. + mock_fork_exec.side_effect = RuntimeError("just testing args") + with self.assertRaises(RuntimeError): + subprocess.run([sys.executable, "-c", "pass"]) + mock_fork_exec.assert_called_once() + self.assertTrue(mock_fork_exec.call_args.args[-1]) + with mock.patch.object(subprocess, '_USE_VFORK', False): + with self.assertRaises(RuntimeError): + subprocess.run([sys.executable, "-c", "pass"]) + self.assertFalse(mock_fork_exec.call_args_list[-1].args[-1]) + + class RunFuncTestCase(BaseTestCase): def run_python(self, code, **kwargs): """Run Python code in a subprocess using subprocess.run""" @@ -3107,7 +3123,7 @@ class POSIXProcessTestCase(BaseTestCase): 1, 2, 3, 4, True, True, False, [], 0, -1, - func) + func, False) # Attempt to prevent # "TypeError: fork_exec() takes exactly N arguments (M given)" # from passing the test. More refactoring to have us start @@ -3156,7 +3172,7 @@ class POSIXProcessTestCase(BaseTestCase): 1, 2, 3, 4, True, True, None, None, None, -1, - None) + None, "no vfork") self.assertIn('fds_to_keep', str(c.exception)) finally: if not gc_enabled: |