aboutsummaryrefslogtreecommitdiff
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2021-01-18 18:34:56 +0100
committerGitHub <noreply@github.com>2021-01-18 18:34:56 +0100
commit314b8787e0c50985ba708034b84ff5b37a1d47de (patch)
tree12941638dbc2d4ad82496a56491b1c3504a79f41 /Python
parentbpo-42923: Add Py_FatalError() test in test_capi (GH-24240) (diff)
downloadcpython-314b8787e0c50985ba708034b84ff5b37a1d47de.tar.gz
cpython-314b8787e0c50985ba708034b84ff5b37a1d47de.tar.bz2
cpython-314b8787e0c50985ba708034b84ff5b37a1d47de.zip
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.c76
-rw-r--r--Python/traceback.c11
2 files changed, 44 insertions, 43 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 9828dffad5c..c02071780b8 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 b82cfd3665c..bd5fd352152 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)