summaryrefslogtreecommitdiffstats
path: root/Lib/test
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2013-08-30 21:38:13 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2013-08-30 21:38:13 (GMT)
commit33fc744ea34f06ae185a28ab22f36130e6d3f5b9 (patch)
tree9b3cf7ec8ee07b25f02f25a477297580f04c9496 /Lib/test
parent30a5445b30bb627a64b2d30788f6db58f6db3ae1 (diff)
downloadcpython-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.py38
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)