Close #20500: Don't trigger PyObject_Str assertion at shutdown

This commit is contained in:
Nick Coghlan 2014-02-09 10:43:21 +10:00
parent c9d1a6b85e
commit d979e4335d
4 changed files with 28 additions and 2 deletions

View File

@ -405,6 +405,24 @@ class CmdLineTest(unittest.TestCase):
'stdout=%r stderr=%r' % (stdout, stderr)) 'stdout=%r stderr=%r' % (stdout, stderr))
self.assertEqual(0, rc) self.assertEqual(0, rc)
def test_issue20500_exit_with_exception_value(self):
script = textwrap.dedent("""\
import sys
error = None
try:
raise ValueError('some text')
except ValueError as err:
error = err
if error:
sys.exit(error)
""")
with temp_dir() as script_dir:
script_name = _make_test_script(script_dir, 'script', script)
exitcode, stdout, stderr = assert_python_failure(script_name)
text = stderr.decode('ascii')
self.assertEqual(text, "some text")
def test_main(): def test_main():
support.run_unittest(CmdLineTest) support.run_unittest(CmdLineTest)

View File

@ -10,7 +10,10 @@ Release date: 2014-02-09
Core and Builtins Core and Builtins
----------------- -----------------
- Issue #20538: UTF-7 incremental decoder produced inconsistant string when - Issue #20500: Displaying an exception at interpreter shutdown no longer
risks triggering an assertion failure in PyObject_Str.
- Issue #20538: UTF-7 incremental decoder produced inconsistent string when
input was truncated in BASE64 section. input was truncated in BASE64 section.
- Issue #20404: io.TextIOWrapper (and hence the open() builtin) now uses the - Issue #20404: io.TextIOWrapper (and hence the open() builtin) now uses the

View File

@ -508,7 +508,7 @@ PyObject_Str(PyObject *v)
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* PyObject_Str() must not be called with an exception set, /* PyObject_Str() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the because it may clear it (directly or indirectly) and so the
caller looses its exception */ caller loses its exception */
assert(!PyErr_Occurred()); assert(!PyErr_Occurred());
#endif #endif

View File

@ -1792,6 +1792,11 @@ handle_system_exit(void)
exitcode = (int)PyLong_AsLong(value); exitcode = (int)PyLong_AsLong(value);
else { else {
PyObject *sys_stderr = _PySys_GetObjectId(&PyId_stderr); PyObject *sys_stderr = _PySys_GetObjectId(&PyId_stderr);
/* We clear the exception here to avoid triggering the assertion
* in PyObject_Str that ensures it won't silently lose exception
* details.
*/
PyErr_Clear();
if (sys_stderr != NULL && sys_stderr != Py_None) { if (sys_stderr != NULL && sys_stderr != Py_None) {
PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW); PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
} else { } else {