summaryrefslogtreecommitdiffstats
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-25 18:27:36 (GMT)
committerGitHub <noreply@github.com>2020-03-25 18:27:36 (GMT)
commit87d3b9db4ade1aa100ee6f065082cb7e85b8992f (patch)
tree85d17fff35bc28beb4a7c6e3a82276f2fa3760d5 /Python/pylifecycle.c
parentace018ca47c03ca699603341b12781b5329d2eaa (diff)
downloadcpython-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.c101
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");