diff -ruN py3k-subprocess2/Lib/test/subprocessdata/fd_status.py py3k-subprocess2-unittest/Lib/test/subprocessdata/fd_status.py --- py3k-subprocess2/Lib/test/subprocessdata/fd_status.py 1970-01-01 02:00:00.000000000 +0200 +++ py3k-subprocess2-unittest/Lib/test/subprocessdata/fd_status.py 2010-12-11 13:14:34.000000000 +0200 @@ -0,0 +1,21 @@ +import errno +import os +import fcntl + +try: + _MAXFD = os.sysconf("SC_OPEN_MAX") +except: + _MAXFD = 256 + +def isopen(fd): + try: + fcntl.fcntl(fd, fcntl.F_GETFD, 0) + except IOError as e: + if e.errno == errno.EBADF: + return False + raise + return True + +if __name__ == "__main__": + print(','.join(str(fd) for fd in range(0, _MAXFD) if isopen(fd))) + diff -ruN py3k-subprocess2/Lib/test/subprocessdata/input_reader.py py3k-subprocess2-unittest/Lib/test/subprocessdata/input_reader.py --- py3k-subprocess2/Lib/test/subprocessdata/input_reader.py 1970-01-01 02:00:00.000000000 +0200 +++ py3k-subprocess2-unittest/Lib/test/subprocessdata/input_reader.py 2010-12-11 14:17:13.000000000 +0200 @@ -0,0 +1,5 @@ +import sys + +if __name__ = "__main__": + for line in sys.stdin: + pass diff -ruN py3k-subprocess2/Lib/test/test_subprocess.py py3k-subprocess2-unittest/Lib/test/test_subprocess.py --- py3k-subprocess2/Lib/test/test_subprocess.py 2010-12-10 20:09:56.000000000 +0200 +++ py3k-subprocess2-unittest/Lib/test/test_subprocess.py 2010-12-11 14:42:27.000000000 +0200 @@ -10,6 +10,7 @@ import re import sysconfig import warnings +import select try: import gc except ImportError: @@ -980,6 +981,69 @@ exitcode = subprocess.call([program, "-c", "pass"], env=envb) self.assertEqual(exitcode, 0) + def test_pipe_cloexec(self): + sleeper = support.findfile("input_reader.py", subdir="subprocessdata") + fd_status = support.findfile("fd_status.py", subdir="subprocessdata") + + p1 = subprocess.Popen([sys.executable, sleeper], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, close_fds=False) + + self.addCleanup(p1.communicate, b'') + + p2 = subprocess.Popen([sys.executable, fd_status], + stdout=subprocess.PIPE, close_fds=False) + + output, error = p2.communicate() + result_fds = set(map(int, output.split(b','))) + unwanted_fds = set([p1.stdin.fileno(), p1.stdout.fileno(), + p1.stderr.fileno()]) + + self.assertFalse(result_fds & unwanted_fds, + "Expected no fds from %r to be open in child, " + "found %r" % + (unwanted_fds, result_fds & unwanted_fds)) + + def test_pipe_cloexec_unix_tools(self): + utils = {} + + path = os.environ['PATH'] + prefixes = path.split(os.pathsep) + cat_candidates = (os.path.join(pfx, "cat") for pfx in prefixes) + grep_candidates = (os.path.join(pfx, "grep") for pfx in prefixes) + + cat = next((f for f in cat_candidates if os.path.isfile(f)), None) + grep = next((f for f in grep_candidates if os.path.isfile(f)), None) + + if cat is None or grep is None: + self.skipTest("cat and grep are required for this test") + + data = b'aaaaaaaaaaaaaaaaaaaa\n' + subdata = b'aaa' + + assert subdata in data, "Test broken" + + p1 = subprocess.Popen([cat], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + close_fds=False) + + p2 = subprocess.Popen([grep, 'a'], + stdin=p1.stdout, stdout=subprocess.PIPE, + close_fds=False) + + self.addCleanup(p1.wait) + self.addCleanup(p2.wait) + self.addCleanup(p1.terminate) + self.addCleanup(p2.terminate) + + p1.stdin.write(data) + p1.stdin.close() + + readfiles, ignored1, ignored2 = select.select([p2.stdout], [], [], 10) + + self.assertTrue(readfiles, "The child hung") + self.assertEqual(p2.stdout.read(), data) + @unittest.skipUnless(mswindows, "Windows specific tests") class Win32ProcessTestCase(BaseTestCase): diff -ruN py3k-subprocess2/Makefile.pre.in py3k-subprocess2-unittest/Makefile.pre.in --- py3k-subprocess2/Makefile.pre.in 2010-12-10 20:09:57.000000000 +0200 +++ py3k-subprocess2-unittest/Makefile.pre.in 2010-12-11 14:08:25.000000000 +0200 @@ -888,7 +888,7 @@ XMLLIBSUBDIRS= xml xml/dom xml/etree xml/parsers xml/sax LIBSUBDIRS= tkinter tkinter/test tkinter/test/test_tkinter \ tkinter/test/test_ttk site-packages test \ - test/decimaltestdata test/xmltestdata \ + test/decimaltestdata test/xmltestdata test/subprocessdata \ test/tracedmodules test/encoded_modules \ concurrent concurrent/futures encodings \ email email/mime email/test email/test/data \ diff -ruN py3k-subprocess2/Tools/msi/msi.py py3k-subprocess2-unittest/Tools/msi/msi.py --- py3k-subprocess2/Tools/msi/msi.py 2010-12-10 20:09:46.000000000 +0200 +++ py3k-subprocess2-unittest/Tools/msi/msi.py 2010-12-11 14:09:21.000000000 +0200 @@ -1035,6 +1035,8 @@ if dir=='xmltestdata': lib.glob("*.xml") lib.add_file("test.xml.out") + if dir=='subprocessdata': + lib.glob("*.py") if dir=='output': lib.glob("test_*") if dir=='sndhdrdata':