diff -r 37671fc60f34 Lib/test/test_subprocess.py --- a/Lib/test/test_subprocess.py Thu Sep 16 17:04:49 2010 +0200 +++ b/Lib/test/test_subprocess.py Thu Sep 16 13:48:21 2010 -0400 @@ -839,6 +839,58 @@ self.assertStderrEqual(stderr, b'') self.assertEqual(p.wait(), -signal.SIGKILL) + def test_remapping_std_fds(self): + # open up some temporary files + temps = (mkstemp(), mkstemp(), mkstemp()) + try: + temp_fds = [fd for fd, fname in temps] + + # unlink the files -- we won't need to reopen them + for fd, fname in temps: + os.unlink(fname) + + # write some data to what will become stdin, and rewind + os.write(temp_fds[1], b"STDIN") + os.lseek(temp_fds[1], 0, 0) + + # move the standard file descriptors out of the way + std_fds = (0,1,2) + saved_fds = [os.dup(fd) for fd in std_fds] + try: + # duplicate the file objects over the standard fd's + for fd in std_fds: + os.dup2(temp_fds[fd], fd) + + # and create corresponding file objects + new_std_files = [os.fdopen(fd, "rw") for fd in std_fds] + + # now use those files in the "wrong" order, so that subprocess + # has to rearrange them in the child + p = subprocess.Popen([sys.executable, "-c", + 'import sys; got = sys.stdin.read(); sys.stdout.write("got %s"%got); sys.stderr.write("err")'], + stdin=new_std_files[1], + stdout=new_std_files[2], + stderr=new_std_files[0]) + p.wait() + + finally: + del new_std_files # close file objects at std_fds + + # restore the original fd's underneath sys.stdin, etc. + for saved, std in zip(saved_fds, std_fds): + os.dup2(saved, std) + os.close(saved) + + for fd in temp_fds: + os.lseek(fd, 0, 0) + + self.assertEqual(os.read(temp_fds[0], 1024), "err") + self.assertEqual(os.read(temp_fds[2], 1024), "got STDIN") + + finally: + for fd in temp_fds: + os.close(fd) + def test_terminate(self): p = self._kill_process('terminate') _, stderr = p.communicate()