Close #20500: Don't trigger PyObject_Str assertion at shutdown
This commit is contained in:
parent
c9d1a6b85e
commit
d979e4335d
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue