diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2013-08-30 21:38:13 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2013-08-30 21:38:13 (GMT) |
commit | 33fc744ea34f06ae185a28ab22f36130e6d3f5b9 (patch) | |
tree | 9b3cf7ec8ee07b25f02f25a477297580f04c9496 /Lib/test | |
parent | 30a5445b30bb627a64b2d30788f6db58f6db3ae1 (diff) | |
download | cpython-33fc744ea34f06ae185a28ab22f36130e6d3f5b9.zip cpython-33fc744ea34f06ae185a28ab22f36130e6d3f5b9.tar.gz cpython-33fc744ea34f06ae185a28ab22f36130e6d3f5b9.tar.bz2 |
Issue #18851: Avoid a double close of subprocess pipes when the child process fails starting.
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_subprocess.py | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py index f43b51c..0efcdbf 100644 --- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -14,6 +14,10 @@ try: import resource except ImportError: resource = None +try: + import threading +except ImportError: + threading = None mswindows = (sys.platform == "win32") @@ -629,6 +633,36 @@ class ProcessTestCase(BaseTestCase): if c.exception.errno not in (errno.ENOENT, errno.EACCES): raise c.exception + @unittest.skipIf(threading is None, "threading required") + def test_double_close_on_error(self): + # Issue #18851 + fds = [] + def open_fds(): + for i in range(20): + fds.extend(os.pipe()) + time.sleep(0.001) + t = threading.Thread(target=open_fds) + t.start() + try: + with self.assertRaises(EnvironmentError): + subprocess.Popen(['nonexisting_i_hope'], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + finally: + t.join() + exc = None + for fd in fds: + # If a double close occurred, some of those fds will + # already have been closed by mistake, and os.close() + # here will raise. + try: + os.close(fd) + except OSError as e: + exc = e + if exc is not None: + raise exc + def test_handles_closed_on_exception(self): # If CreateProcess exits with an error, ensure the # duplicate output handles are released @@ -783,7 +817,7 @@ class POSIXProcessTestCase(BaseTestCase): def _execute_child( self, args, executable, preexec_fn, close_fds, cwd, env, - universal_newlines, startupinfo, creationflags, shell, + universal_newlines, startupinfo, creationflags, shell, to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite): @@ -791,7 +825,7 @@ class POSIXProcessTestCase(BaseTestCase): subprocess.Popen._execute_child( self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, - startupinfo, creationflags, shell, + startupinfo, creationflags, shell, to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite) |