Skip to content

Commit a85a1d3

Browse files
authored
bpo-36829: sys.excepthook and sys.unraisablehook flush (GH-13620)
sys.excepthook() and sys.unraisablehook() now explicitly flush the file (usually sys.stderr). If file.flush() fails, sys.excepthook() silently ignores the error, whereas sys.unraisablehook() logs the new exception.
1 parent 51ddab8 commit a85a1d3

File tree

2 files changed

+19
-0
lines changed

2 files changed

+19
-0
lines changed

Python/errors.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern "C" {
2626

2727
_Py_IDENTIFIER(builtins);
2828
_Py_IDENTIFIER(stderr);
29+
_Py_IDENTIFIER(flush);
2930

3031

3132
/* Forward declarations */
@@ -1254,6 +1255,14 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
12541255
if (PyFile_WriteString("\n", file) < 0) {
12551256
return -1;
12561257
}
1258+
1259+
/* Explicitly call file.flush() */
1260+
PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
1261+
if (!res) {
1262+
return -1;
1263+
}
1264+
Py_DECREF(res);
1265+
12571266
return 0;
12581267
}
12591268

Python/pythonrun.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,16 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t
978978
}
979979
print_exception_recursive(file, value, seen);
980980
Py_XDECREF(seen);
981+
982+
/* Call file.flush() */
983+
PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
984+
if (!res) {
985+
/* Silently ignore file.flush() error */
986+
PyErr_Clear();
987+
}
988+
else {
989+
Py_DECREF(res);
990+
}
981991
}
982992

983993
void

0 commit comments

Comments
 (0)