Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d979e43

Browse files
committed
Close #20500: Don't trigger PyObject_Str assertion at shutdown
1 parent c9d1a6b commit d979e43

4 files changed

Lines changed: 28 additions & 2 deletions

File tree

Lib/test/test_cmd_line_script.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,24 @@ def test_non_ascii(self):
405405
'stdout=%r stderr=%r' % (stdout, stderr))
406406
self.assertEqual(0, rc)
407407

408+
def test_issue20500_exit_with_exception_value(self):
409+
script = textwrap.dedent("""\
410+
import sys
411+
error = None
412+
try:
413+
raise ValueError('some text')
414+
except ValueError as err:
415+
error = err
416+
417+
if error:
418+
sys.exit(error)
419+
""")
420+
with temp_dir() as script_dir:
421+
script_name = _make_test_script(script_dir, 'script', script)
422+
exitcode, stdout, stderr = assert_python_failure(script_name)
423+
text = stderr.decode('ascii')
424+
self.assertEqual(text, "some text")
425+
408426

409427
def test_main():
410428
support.run_unittest(CmdLineTest)

Misc/NEWS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ Release date: 2014-02-09
1010
Core and Builtins
1111
-----------------
1212

13-
- Issue #20538: UTF-7 incremental decoder produced inconsistant string when
13+
- Issue #20500: Displaying an exception at interpreter shutdown no longer
14+
risks triggering an assertion failure in PyObject_Str.
15+
16+
- Issue #20538: UTF-7 incremental decoder produced inconsistent string when
1417
input was truncated in BASE64 section.
1518

1619
- Issue #20404: io.TextIOWrapper (and hence the open() builtin) now uses the

Objects/object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ PyObject_Str(PyObject *v)
508508
#ifdef Py_DEBUG
509509
/* PyObject_Str() must not be called with an exception set,
510510
because it may clear it (directly or indirectly) and so the
511-
caller looses its exception */
511+
caller loses its exception */
512512
assert(!PyErr_Occurred());
513513
#endif
514514

Python/pythonrun.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,6 +1792,11 @@ handle_system_exit(void)
17921792
exitcode = (int)PyLong_AsLong(value);
17931793
else {
17941794
PyObject *sys_stderr = _PySys_GetObjectId(&PyId_stderr);
1795+
/* We clear the exception here to avoid triggering the assertion
1796+
* in PyObject_Str that ensures it won't silently lose exception
1797+
* details.
1798+
*/
1799+
PyErr_Clear();
17951800
if (sys_stderr != NULL && sys_stderr != Py_None) {
17961801
PyFile_WriteObject(value, sys_stderr, Py_PRINT_RAW);
17971802
} else {

0 commit comments

Comments
 (0)