diff options
author | Victor Stinner <vstinner@python.org> | 2020-03-25 18:27:36 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-25 18:27:36 (GMT) |
commit | 87d3b9db4ade1aa100ee6f065082cb7e85b8992f (patch) | |
tree | 85d17fff35bc28beb4a7c6e3a82276f2fa3760d5 /Python/pylifecycle.c | |
parent | ace018ca47c03ca699603341b12781b5329d2eaa (diff) | |
download | cpython-87d3b9db4ade1aa100ee6f065082cb7e85b8992f.zip cpython-87d3b9db4ade1aa100ee6f065082cb7e85b8992f.tar.gz cpython-87d3b9db4ade1aa100ee6f065082cb7e85b8992f.tar.bz2 |
bpo-39882: Add _Py_FatalErrorFormat() function (GH-19157)
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 101 |
1 files changed, 73 insertions, 28 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index b7019e3..08a727f 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -2176,33 +2176,50 @@ fatal_error_dump_runtime(FILE *stream, _PyRuntimeState *runtime) } +static inline void _Py_NO_RETURN +fatal_error_exit(int status) +{ + if (status < 0) { +#if defined(MS_WINDOWS) && defined(_DEBUG) + DebugBreak(); +#endif + abort(); + } + else { + exit(status); + } +} + + static void _Py_NO_RETURN -fatal_error(const char *prefix, const char *msg, int status) +fatal_error(FILE *stream, int header, const char *prefix, const char *msg, + int status) { - FILE *stream = stderr; const int fd = fileno(stream); static int reentrant = 0; if (reentrant) { /* Py_FatalError() caused a second fatal error. Example: flush_std_files() raises a recursion error. */ - goto exit; + fatal_error_exit(status); } reentrant = 1; - fprintf(stream, "Fatal Python error: "); - if (prefix) { - fputs(prefix, stream); - fputs(": ", stream); - } - if (msg) { - fputs(msg, stream); - } - else { - fprintf(stream, "<message not set>"); + if (header) { + fprintf(stream, "Fatal Python error: "); + if (prefix) { + fputs(prefix, stream); + fputs(": ", stream); + } + if (msg) { + fputs(msg, stream); + } + else { + fprintf(stream, "<message not set>"); + } + fputs("\n", stream); + fflush(stream); } - fputs("\n", stream); - fflush(stream); /* it helps in Windows debug build */ _PyRuntimeState *runtime = &_PyRuntime; fatal_error_dump_runtime(stream, runtime); @@ -2250,32 +2267,60 @@ fatal_error(const char *prefix, const char *msg, int status) fatal_output_debug(msg); #endif /* MS_WINDOWS */ -exit: - if (status < 0) { -#if defined(MS_WINDOWS) && defined(_DEBUG) - DebugBreak(); -#endif - abort(); - } - else { - exit(status); - } + fatal_error_exit(status); } + #undef Py_FatalError void _Py_NO_RETURN Py_FatalError(const char *msg) { - fatal_error(NULL, msg, -1); + fatal_error(stderr, 1, NULL, msg, -1); } + void _Py_NO_RETURN _Py_FatalErrorFunc(const char *func, const char *msg) { - fatal_error(func, msg, -1); + fatal_error(stderr, 1, func, msg, -1); +} + + +void _Py_NO_RETURN +_Py_FatalErrorFormat(const char *func, const char *format, ...) +{ + static int reentrant = 0; + if (reentrant) { + /* _Py_FatalErrorFormat() caused a second fatal error */ + fatal_error_exit(-1); + } + reentrant = 1; + + FILE *stream = stderr; + fprintf(stream, "Fatal Python error: "); + if (func) { + fputs(func, stream); + fputs(": ", stream); + } + fflush(stream); + + va_list vargs; +#ifdef HAVE_STDARG_PROTOTYPES + va_start(vargs, format); +#else + va_start(vargs); +#endif + vfprintf(stream, format, vargs); + va_end(vargs); + + fputs("\n", stream); + fflush(stream); + + fatal_error(stream, 0, NULL, NULL, -1); } + void _Py_NO_RETURN Py_ExitStatusException(PyStatus status) { @@ -2283,7 +2328,7 @@ Py_ExitStatusException(PyStatus status) exit(status.exitcode); } else if (_PyStatus_IS_ERROR(status)) { - fatal_error(status.func, status.err_msg, 1); + fatal_error(stderr, 1, status.func, status.err_msg, 1); } else { Py_FatalError("Py_ExitStatusException() must not be called on success"); |