mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
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.
This commit is contained in:
parent
e232025025
commit
314b8787e0
3 changed files with 47 additions and 50 deletions
|
@ -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");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue