diff options
author | Victor Stinner <vstinner@python.org> | 2021-01-18 17:34:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-01-18 17:34:56 (GMT) |
commit | 314b8787e0c50985ba708034b84ff5b37a1d47de (patch) | |
tree | 12941638dbc2d4ad82496a56491b1c3504a79f41 /Python | |
parent | e232025025c8bd07c1d1b12a583a80c4a673f077 (diff) | |
download | cpython-314b8787e0c50985ba708034b84ff5b37a1d47de.zip cpython-314b8787e0c50985ba708034b84ff5b37a1d47de.tar.gz cpython-314b8787e0c50985ba708034b84ff5b37a1d47de.tar.bz2 |
bpo-42923: Py_FatalError() avoids fprintf() (GH-24242)
* Replace buffered fprintf() with unbuffered _Py_write_noraise()
in Py_FatalError().
* _Py_DumpHexadecimal() now accepts uintptr_t.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/pylifecycle.c | 76 | ||||
-rw-r--r-- | Python/traceback.c | 11 |
2 files changed, 44 insertions, 43 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 9828dff..c020717 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -38,6 +38,9 @@ #endif +#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str)) + + _Py_IDENTIFIER(flush); _Py_IDENTIFIER(name); _Py_IDENTIFIER(stdin); @@ -2348,8 +2351,7 @@ static void _Py_FatalError_DumpTracebacks(int fd, PyInterpreterState *interp, PyThreadState *tstate) { - fputc('\n', stderr); - fflush(stderr); + PUTS(fd, "\n"); /* display the current Python stack */ _Py_DumpTracebackThreads(fd, interp, tstate); @@ -2451,30 +2453,31 @@ fatal_output_debug(const char *msg) static void -fatal_error_dump_runtime(FILE *stream, _PyRuntimeState *runtime) +fatal_error_dump_runtime(int fd, _PyRuntimeState *runtime) { - fprintf(stream, "Python runtime state: "); + PUTS(fd, "Python runtime state: "); PyThreadState *finalizing = _PyRuntimeState_GetFinalizing(runtime); if (finalizing) { - fprintf(stream, "finalizing (tstate=%p)", finalizing); + PUTS(fd, "finalizing (tstate=0x"); + _Py_DumpHexadecimal(fd, (uintptr_t)finalizing, sizeof(finalizing) * 2); + PUTS(fd, ")"); } else if (runtime->initialized) { - fprintf(stream, "initialized"); + PUTS(fd, "initialized"); } else if (runtime->core_initialized) { - fprintf(stream, "core initialized"); + PUTS(fd, "core initialized"); } else if (runtime->preinitialized) { - fprintf(stream, "preinitialized"); + PUTS(fd, "preinitialized"); } else if (runtime->preinitializing) { - fprintf(stream, "preinitializing"); + PUTS(fd, "preinitializing"); } else { - fprintf(stream, "unknown"); + PUTS(fd, "unknown"); } - fprintf(stream, "\n"); - fflush(stream); + PUTS(fd, "\n"); } @@ -2494,10 +2497,9 @@ fatal_error_exit(int status) static void _Py_NO_RETURN -fatal_error(FILE *stream, int header, const char *prefix, const char *msg, +fatal_error(int fd, int header, const char *prefix, const char *msg, int status) { - const int fd = fileno(stream); static int reentrant = 0; if (reentrant) { @@ -2508,29 +2510,22 @@ fatal_error(FILE *stream, int header, const char *prefix, const char *msg, reentrant = 1; if (header) { - fprintf(stream, "Fatal Python error: "); + PUTS(fd, "Fatal Python error: "); if (prefix) { - fputs(prefix, stream); - fputs(": ", stream); + PUTS(fd, prefix); + PUTS(fd, ": "); } if (msg) { - fputs(msg, stream); + PUTS(fd, msg); } else { - fprintf(stream, "<message not set>"); + PUTS(fd, "<message not set>"); } - fputs("\n", stream); - fflush(stream); + PUTS(fd, "\n"); } _PyRuntimeState *runtime = &_PyRuntime; - fatal_error_dump_runtime(stream, runtime); - - PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); - PyInterpreterState *interp = NULL; - if (tstate != NULL) { - interp = tstate->interp; - } + fatal_error_dump_runtime(fd, runtime); /* Check if the current thread has a Python thread state and holds the GIL. @@ -2540,8 +2535,17 @@ fatal_error(FILE *stream, int header, const char *prefix, const char *msg, tss_tstate != tstate if the current Python thread does not hold the GIL. */ + PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); + PyInterpreterState *interp = NULL; PyThreadState *tss_tstate = PyGILState_GetThisThreadState(); + if (tstate != NULL) { + interp = tstate->interp; + } + else if (tss_tstate != NULL) { + interp = tss_tstate->interp; + } int has_tstate_and_gil = (tss_tstate != NULL && tss_tstate == tstate); + if (has_tstate_and_gil) { /* If an exception is set, print the exception with its traceback */ if (!_Py_FatalError_PrintExc(tss_tstate)) { @@ -2578,14 +2582,14 @@ fatal_error(FILE *stream, int header, const char *prefix, const char *msg, void _Py_NO_RETURN Py_FatalError(const char *msg) { - fatal_error(stderr, 1, NULL, msg, -1); + fatal_error(fileno(stderr), 1, NULL, msg, -1); } void _Py_NO_RETURN _Py_FatalErrorFunc(const char *func, const char *msg) { - fatal_error(stderr, 1, func, msg, -1); + fatal_error(fileno(stderr), 1, func, msg, -1); } @@ -2600,12 +2604,12 @@ _Py_FatalErrorFormat(const char *func, const char *format, ...) reentrant = 1; FILE *stream = stderr; - fprintf(stream, "Fatal Python error: "); + const int fd = fileno(stream); + PUTS(fd, "Fatal Python error: "); if (func) { - fputs(func, stream); - fputs(": ", stream); + PUTS(fd, func); + PUTS(fd, ": "); } - fflush(stream); va_list vargs; #ifdef HAVE_STDARG_PROTOTYPES @@ -2619,7 +2623,7 @@ _Py_FatalErrorFormat(const char *func, const char *format, ...) fputs("\n", stream); fflush(stream); - fatal_error(stream, 0, NULL, NULL, -1); + fatal_error(fd, 0, NULL, NULL, -1); } @@ -2630,7 +2634,7 @@ Py_ExitStatusException(PyStatus status) exit(status.exitcode); } else if (_PyStatus_IS_ERROR(status)) { - fatal_error(stderr, 1, status.func, status.err_msg, 1); + fatal_error(fileno(stderr), 1, status.func, status.err_msg, 1); } else { Py_FatalError("Py_ExitStatusException() must not be called on success"); diff --git a/Python/traceback.c b/Python/traceback.c index b82cfd3..bd5fd35 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -649,15 +649,12 @@ _Py_DumpDecimal(int fd, unsigned long value) _Py_write_noraise(fd, ptr, end - ptr); } -/* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits, - and write it into the file fd. - - This function is signal safe. */ - +/* Format an integer as hexadecimal with width digits into fd file descriptor. + The function is signal safe. */ void -_Py_DumpHexadecimal(int fd, unsigned long value, Py_ssize_t width) +_Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width) { - char buffer[sizeof(unsigned long) * 2 + 1], *ptr, *end; + char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end; const Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1; if (width > size) |