summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-05-28 16:01:17 +0200
committerGitHub <noreply@github.com>2019-05-28 16:01:17 +0200
commita85a1d337d26a65036e427341d15e3979f7e9ced (patch)
treeb355ad22fb8ca020f6572c48519e2fdf641db47a
parent51ddab8dae056867f3595ab3400bffc93f67c8d4 (diff)
downloadcpython-git-a85a1d337d26a65036e427341d15e3979f7e9ced.tar.gz
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.
-rw-r--r--Python/errors.c9
-rw-r--r--Python/pythonrun.c10
2 files changed, 19 insertions, 0 deletions
diff --git a/Python/errors.c b/Python/errors.c
index bd33d4d340..8a94afdd8c 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -26,6 +26,7 @@ extern "C" {
_Py_IDENTIFIER(builtins);
_Py_IDENTIFIER(stderr);
+_Py_IDENTIFIER(flush);
/* Forward declarations */
@@ -1254,6 +1255,14 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type,
if (PyFile_WriteString("\n", file) < 0) {
return -1;
}
+
+ /* Explicitly call file.flush() */
+ PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
+ if (!res) {
+ return -1;
+ }
+ Py_DECREF(res);
+
return 0;
}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index ba1d1cf02f..ace9f2f987 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -978,6 +978,16 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t
}
print_exception_recursive(file, value, seen);
Py_XDECREF(seen);
+
+ /* Call file.flush() */
+ PyObject *res = _PyObject_CallMethodId(file, &PyId_flush, NULL);
+ if (!res) {
+ /* Silently ignore file.flush() error */
+ PyErr_Clear();
+ }
+ else {
+ Py_DECREF(res);
+ }
}
void