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))
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():
support.run_unittest(CmdLineTest)

View File

@ -10,7 +10,10 @@ Release date: 2014-02-09
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.
- 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
/* PyObject_Str() must not be called with an exception set,
because it may clear it (directly or indirectly) and so the
caller looses its exception */
caller loses its exception */
assert(!PyErr_Occurred());
#endif

View File

@ -1792,6 +1792,11 @@ handle_system_exit(void)
exitcode = (int)PyLong_AsLong(value);
else {
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) {
PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
} else {