diff options
-rw-r--r-- | Lib/test/test_cmd_line.py | 22 | ||||
-rw-r--r-- | Python/pythonrun.c | 20 |
2 files changed, 37 insertions, 5 deletions
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index db94a40..19089a4 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -13,18 +13,25 @@ def _spawn_python(*args): stdout=subprocess.PIPE, stderr=subprocess.STDOUT) def _kill_python(p): + return _kill_python_and_exit_code(p)[0] + +def _kill_python_and_exit_code(p): p.stdin.close() data = p.stdout.read() p.stdout.close() # try to cleanup the child so we don't appear to leak when running # with regrtest -R. This should be a no-op on Windows. subprocess._cleanup() - return data + returncode = p.wait() + return data, returncode class CmdLineTest(unittest.TestCase): def start_python(self, *args): + return self.start_python_and_exit_code(*args)[0] + + def start_python_and_exit_code(self, *args): p = _spawn_python(*args) - return _kill_python(p) + return _kill_python_and_exit_code(p) def exit_code(self, *args): cmd_line = [sys.executable, '-E'] @@ -61,6 +68,17 @@ class CmdLineTest(unittest.TestCase): version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii") self.assertTrue(self.start_python('-V').startswith(version)) + def test_verbose(self): + # -v causes imports to write to stderr. If the write to + # stderr itself causes an import to happen (for the output + # codec), a recursion loop can occur. + data, rc = self.start_python_and_exit_code('-v') + self.assertEqual(rc, 0) + self.assertTrue(b'stack overflow' not in data) + data, rc = self.start_python_and_exit_code('-vv') + self.assertEqual(rc, 0) + self.assertTrue(b'stack overflow' not in data) + def test_run_module(self): # Test expected operation of the '-m' switch # Switch needs an argument diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 6af7aec..d65d12d 100644 --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -512,7 +512,7 @@ Py_Finalize(void) /* reset file system default encoding */ if (!Py_HasFileSystemDefaultEncoding) { free((char*)Py_FileSystemDefaultEncoding); - Py_FileSystemDefaultEncoding = NULL; + Py_FileSystemDefaultEncoding = NULL; } /* XXX Still allocated: @@ -733,6 +733,7 @@ initstdio(void) PyObject *m; PyObject *std = NULL; int status = 0, fd; + PyObject * encoding_attr; /* Hack to avoid a nasty recursion issue when Python is invoked in verbose mode: pre-import the Latin-1 and UTF-8 codecs */ @@ -823,6 +824,19 @@ initstdio(void) goto error; } } /* if (fd < 0) */ + + /* Same as hack above, pre-import stderr's codec to avoid recursion + when import.c tries to write to stderr in verbose mode. */ + encoding_attr = PyObject_GetAttrString(std, "encoding"); + if (encoding_attr != NULL) { + const char * encoding; + encoding = PyUnicode_AsString(encoding_attr); + if (encoding != NULL) { + _PyCodec_Lookup(encoding); + } + } + PyErr_Clear(); /* Not a fatal error if codec isn't available */ + PySys_SetObject("__stderr__", std); PySys_SetObject("stderr", std); Py_DECREF(std); @@ -1900,8 +1914,8 @@ PyOS_CheckStack(void) alloca(PYOS_STACK_MARGIN * sizeof(void*)); return 0; } __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ? - EXCEPTION_EXECUTE_HANDLER : - EXCEPTION_CONTINUE_SEARCH) { + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { int errcode = _resetstkoflw(); if (errcode) { |