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

Skip to content

Commit e9fb319

Browse files
author
Victor Stinner
committed
handle_system_exit() flushs files to warranty the output order
PyObject_Print() writes into the C object stderr, whereas PySys_WriteStderr() writes into the Python object sys.stderr. Each object has its own buffer, so call sys.stderr.flush() and fflush(stderr).
1 parent 372ac5e commit e9fb319

2 files changed

Lines changed: 22 additions & 8 deletions

File tree

Lib/test/test_sys.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ def test_excepthook(self):
8686
# Python/pythonrun.c::PyErr_PrintEx() is tricky.
8787

8888
def test_exit(self):
89+
import subprocess
90+
8991
self.assertRaises(TypeError, sys.exit, 42, 42)
9092

9193
# call without argument
@@ -140,20 +142,28 @@ def test_exit(self):
140142
self.fail("no exception")
141143

142144
# test that the exit machinery handles SystemExits properly
143-
import subprocess
144145
rc = subprocess.call([sys.executable, "-c",
145146
"raise SystemExit(47)"])
146147
self.assertEqual(rc, 47)
147148

149+
def check_exit_message(code, expected):
150+
process = subprocess.Popen([sys.executable, "-c", code],
151+
stderr=subprocess.PIPE)
152+
stdout, stderr = process.communicate()
153+
self.assertEqual(process.returncode, 1)
154+
self.assertTrue(stderr.startswith(expected), stderr)
155+
156+
# test that stderr buffer if flushed before the exit message is written
157+
# into stderr
158+
check_exit_message(
159+
r'import sys; sys.stderr.write("unflushed,"); sys.exit("message")',
160+
b"unflushed,message")
161+
148162
# test that the exit message is written with backslashreplace error
149163
# handler to stderr
150-
import subprocess
151-
code = r'import sys; sys.exit("surrogates:\uDCFF")'
152-
process = subprocess.Popen([sys.executable, "-c", code],
153-
stderr=subprocess.PIPE)
154-
stdout, stderr = process.communicate()
155-
self.assertEqual(process.returncode, 1)
156-
self.assertTrue(stderr.startswith(b"surrogates:\\udcff"), stderr)
164+
check_exit_message(
165+
r'import sys; sys.exit("surrogates:\uDCFF")',
166+
b"surrogates:\\udcff")
157167

158168
def test_getdefaultencoding(self):
159169
self.assertRaises(TypeError, sys.getdefaultencoding, 42)

Python/pythonrun.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,7 +1367,11 @@ handle_system_exit(void)
13671367
if (PyLong_Check(value))
13681368
exitcode = (int)PyLong_AsLong(value);
13691369
else {
1370+
PyObject *sys_stderr = PySys_GetObject("stderr");
1371+
if (sys_stderr != NULL)
1372+
PyObject_CallMethod(sys_stderr, "flush", NULL);
13701373
PyObject_Print(value, stderr, Py_PRINT_RAW);
1374+
fflush(stderr);
13711375
PySys_WriteStderr("\n");
13721376
exitcode = 1;
13731377
}

0 commit comments

Comments
 (0)