diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-11-28 18:08:36 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-11-28 18:08:36 (GMT) |
commit | 11942a58a190a235f69e8fb193d08a4fca2bcf3c (patch) | |
tree | da2ad80d9d31ec671452a22c0a15cd840ec99c7b | |
parent | 22b9b379159f953ad4805980644414354030624f (diff) | |
download | cpython-11942a58a190a235f69e8fb193d08a4fca2bcf3c.zip cpython-11942a58a190a235f69e8fb193d08a4fca2bcf3c.tar.gz cpython-11942a58a190a235f69e8fb193d08a4fca2bcf3c.tar.bz2 |
Issue #7111: Python can now be run without a stdin, stdout or stderr stream.
It was already the case with Python 2. However, the corresponding
sys module entries are now set to None (instead of an unusable file object).
-rw-r--r-- | Lib/test/test_cmd_line.py | 39 | ||||
-rw-r--r-- | Misc/NEWS | 4 | ||||
-rw-r--r-- | Python/pythonrun.c | 31 |
3 files changed, 59 insertions, 15 deletions
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index 8167e78..2fca25e 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -291,6 +291,45 @@ class CmdLineTest(unittest.TestCase): rc, out, err = assert_python_ok('-c', code) self.assertEqual(b'', err) + # Issue #7111: Python should work without standard streams + + @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics") + def _test_no_stdio(self, streams): + code = """if 1: + import os, sys + for i, s in enumerate({streams}): + if getattr(sys, s) is not None: + os._exit(i + 1) + os._exit(42)""".format(streams=streams) + def preexec(): + if 'stdin' in streams: + os.close(0) + if 'stdout' in streams: + os.close(1) + if 'stderr' in streams: + os.close(2) + p = subprocess.Popen( + [sys.executable, "-E", "-c", code], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + preexec_fn=preexec) + out, err = p.communicate() + self.assertEqual(test.support.strip_python_stderr(err), b'') + self.assertEqual(p.returncode, 42) + + def test_no_stdin(self): + self._test_no_stdio(['stdin']) + + def test_no_stdout(self): + self._test_no_stdio(['stdout']) + + def test_no_stderr(self): + self._test_no_stdio(['stderr']) + + def test_no_std_streams(self): + self._test_no_stdio(['stdin', 'stdout', 'stderr']) + def test_main(): test.support.run_unittest(CmdLineTest) @@ -10,6 +10,10 @@ What's New in Python 3.2.3? Core and Builtins ----------------- +- Issue #7111: Python can now be run without a stdin, stdout or stderr + stream. It was already the case with Python 2. However, the corresponding + sys module entries are now set to None (instead of an unusable file object). + - Issue #13436: Fix a bogus error message when an AST object was passed an invalid integer value. diff --git a/Python/pythonrun.c b/Python/pythonrun.c index fe92d30..4b0ac13 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -892,6 +892,19 @@ error: return NULL; } +static int +is_valid_fd(int fd) +{ + int dummy_fd; + if (fd < 0 || !_PyVerify_fd(fd)) + return 0; + dummy_fd = dup(fd); + if (dummy_fd < 0) + return 0; + close(dummy_fd); + return 1; +} + /* Initialize sys.stdin, stdout, stderr and builtins.open */ static int initstdio(void) @@ -951,13 +964,9 @@ initstdio(void) * and fileno() may point to an invalid file descriptor. For example * GUI apps don't have valid standard streams by default. */ - if (fd < 0) { -#ifdef MS_WINDOWS + if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); -#else - goto error; -#endif } else { std = create_stdio(iomod, fd, 0, "<stdin>", encoding, errors); @@ -970,13 +979,9 @@ initstdio(void) /* Set sys.stdout */ fd = fileno(stdout); - if (fd < 0) { -#ifdef MS_WINDOWS + if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); -#else - goto error; -#endif } else { std = create_stdio(iomod, fd, 1, "<stdout>", encoding, errors); @@ -990,13 +995,9 @@ initstdio(void) #if 1 /* Disable this if you have trouble debugging bootstrap stuff */ /* Set sys.stderr, replaces the preliminary stderr */ fd = fileno(stderr); - if (fd < 0) { -#ifdef MS_WINDOWS + if (!is_valid_fd(fd)) { std = Py_None; Py_INCREF(std); -#else - goto error; -#endif } else { std = create_stdio(iomod, fd, 1, "<stderr>", encoding, "backslashreplace"); |