bpo-39882: Add _Py_FatalErrorFormat() function (GH-19157)

This commit is contained in:
Victor Stinner 2020-03-25 19:27:36 +01:00 committed by GitHub
parent ace018ca47
commit 87d3b9db4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 158 additions and 110 deletions

View File

@ -182,6 +182,11 @@ PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc(
const char *func, const char *func,
const char *message); const char *message);
PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFormat(
const char *func,
const char *format,
...);
#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, message) #define Py_FatalError(message) _Py_FatalErrorFunc(__func__, message)
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -292,12 +292,11 @@ _enter_buffered_busy(buffered *self)
} }
Py_END_ALLOW_THREADS Py_END_ALLOW_THREADS
if (relax_locking && st != PY_LOCK_ACQUIRED) { if (relax_locking && st != PY_LOCK_ACQUIRED) {
PyObject *msgobj = PyUnicode_FromFormat( PyObject *ascii = PyObject_ASCII((PyObject*)self);
"could not acquire lock for %A at interpreter " _Py_FatalErrorFormat(__func__,
"could not acquire lock for %s at interpreter "
"shutdown, possibly due to daemon threads", "shutdown, possibly due to daemon threads",
(PyObject *) self); ascii ? PyUnicode_AsUTF8(ascii) : "<ascii(self) failed>");
const char *msg = PyUnicode_AsUTF8(msgobj);
Py_FatalError(msg);
} }
return 1; return 1;
} }

View File

@ -46,7 +46,8 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
"%s returned NULL without setting an error", "%s returned NULL without setting an error",
where); where);
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */ /* Ensure that the bug is caught in debug mode.
Py_FatalError() logs the SystemError exception raised above. */
Py_FatalError("a function returned NULL without setting an error"); Py_FatalError("a function returned NULL without setting an error");
#endif #endif
return NULL; return NULL;
@ -67,7 +68,8 @@ _Py_CheckFunctionResult(PyThreadState *tstate, PyObject *callable,
"%s returned a result with an error set", where); "%s returned a result with an error set", where);
} }
#ifdef Py_DEBUG #ifdef Py_DEBUG
/* Ensure that the bug is caught in debug mode */ /* Ensure that the bug is caught in debug mode.
Py_FatalError() logs the SystemError exception raised above. */
Py_FatalError("a function returned a result with an error set"); Py_FatalError("a function returned a result with an error set");
#endif #endif
return NULL; return NULL;

View File

@ -957,8 +957,9 @@ void
PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level) PyFrame_BlockSetup(PyFrameObject *f, int type, int handler, int level)
{ {
PyTryBlock *b; PyTryBlock *b;
if (f->f_iblock >= CO_MAXBLOCKS) if (f->f_iblock >= CO_MAXBLOCKS) {
Py_FatalError("XXX block stack overflow"); Py_FatalError("block stack overflow");
}
b = &f->f_blockstack[f->f_iblock++]; b = &f->f_blockstack[f->f_iblock++];
b->b_type = type; b->b_type = type;
b->b_level = level; b->b_level = level;
@ -969,8 +970,9 @@ PyTryBlock *
PyFrame_BlockPop(PyFrameObject *f) PyFrame_BlockPop(PyFrameObject *f)
{ {
PyTryBlock *b; PyTryBlock *b;
if (f->f_iblock <= 0) if (f->f_iblock <= 0) {
Py_FatalError("XXX block stack underflow"); Py_FatalError("block stack underflow");
}
b = &f->f_blockstack[--f->f_iblock]; b = &f->f_blockstack[--f->f_iblock];
return b; return b;
} }

View File

@ -2361,26 +2361,22 @@ _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
static void static void
_PyMem_DebugCheckAddress(const char *func, char api, const void *p) _PyMem_DebugCheckAddress(const char *func, char api, const void *p)
{ {
assert(p != NULL);
const uint8_t *q = (const uint8_t *)p; const uint8_t *q = (const uint8_t *)p;
char msgbuf[64];
const char *msg;
size_t nbytes; size_t nbytes;
const uint8_t *tail; const uint8_t *tail;
int i; int i;
char id; char id;
if (p == NULL) {
msg = "didn't expect a NULL pointer";
goto error;
}
/* Check the API id */ /* Check the API id */
id = (char)q[-SST]; id = (char)q[-SST];
if (id != api) { if (id != api) {
msg = msgbuf; _PyObject_DebugDumpAddress(p);
snprintf(msgbuf, sizeof(msgbuf), "bad ID: Allocated using API '%c', verified using API '%c'", id, api); _Py_FatalErrorFormat(func,
msgbuf[sizeof(msgbuf)-1] = 0; "bad ID: Allocated using API '%c', "
goto error; "verified using API '%c'",
id, api);
} }
/* Check the stuff at the start of p first: if there's underwrite /* Check the stuff at the start of p first: if there's underwrite
@ -2389,8 +2385,8 @@ _PyMem_DebugCheckAddress(const char *func, char api, const void *p)
*/ */
for (i = SST-1; i >= 1; --i) { for (i = SST-1; i >= 1; --i) {
if (*(q-i) != PYMEM_FORBIDDENBYTE) { if (*(q-i) != PYMEM_FORBIDDENBYTE) {
msg = "bad leading pad byte"; _PyObject_DebugDumpAddress(p);
goto error; _Py_FatalErrorFunc(func, "bad leading pad byte");
} }
} }
@ -2398,16 +2394,10 @@ _PyMem_DebugCheckAddress(const char *func, char api, const void *p)
tail = q + nbytes; tail = q + nbytes;
for (i = 0; i < SST; ++i) { for (i = 0; i < SST; ++i) {
if (tail[i] != PYMEM_FORBIDDENBYTE) { if (tail[i] != PYMEM_FORBIDDENBYTE) {
msg = "bad trailing pad byte"; _PyObject_DebugDumpAddress(p);
goto error; _Py_FatalErrorFunc(func, "bad trailing pad byte");
} }
} }
return;
error:
_PyObject_DebugDumpAddress(p);
_Py_FatalErrorFunc(func, msg);
} }
/* Display info to stderr about the memory block at p. */ /* Display info to stderr about the memory block at p. */

View File

@ -41,7 +41,7 @@ PyGrammar_LabelRepr(label *lb)
} }
} }
else { else {
Py_FatalError("invalid label"); Py_FatalError("invalid grammar label");
return NULL; return NULL;
} }
} }

View File

@ -1032,7 +1032,7 @@ tok_backup(struct tok_state *tok, int c)
{ {
if (c != EOF) { if (c != EOF) {
if (--tok->cur < tok->buf) { if (--tok->cur < tok->buf) {
Py_FatalError("beginning of buffer"); Py_FatalError("tokenizer beginning of buffer");
} }
if (*tok->cur != c) { if (*tok->cur != c) {
*tok->cur = c; *tok->cur = c;

View File

@ -727,11 +727,8 @@ num_stmts(const node *n)
return l; return l;
} }
default: { default: {
char buf[128]; _Py_FatalErrorFormat(__func__, "Non-statement found: %d %d",
TYPE(n), NCH(n));
sprintf(buf, "Non-statement found: %d %d",
TYPE(n), NCH(n));
Py_FatalError(buf);
} }
} }
Py_UNREACHABLE(); Py_UNREACHABLE();

View File

@ -1876,18 +1876,15 @@ get_ref_type(struct compiler *c, PyObject *name)
return CELL; return CELL;
scope = PyST_GetScope(c->u->u_ste, name); scope = PyST_GetScope(c->u->u_ste, name);
if (scope == 0) { if (scope == 0) {
char buf[350]; _Py_FatalErrorFormat(__func__,
PyOS_snprintf(buf, sizeof(buf), "unknown scope for %.100s in %.100s(%s)\n"
"unknown scope for %.100s in %.100s(%s)\n" "symbols: %s\nlocals: %s\nglobals: %s",
"symbols: %s\nlocals: %s\nglobals: %s", PyUnicode_AsUTF8(name),
PyUnicode_AsUTF8(name), PyUnicode_AsUTF8(c->u->u_name),
PyUnicode_AsUTF8(c->u->u_name), PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_id)), PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_ste->ste_symbols)), PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)),
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_varnames)), PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names)));
PyUnicode_AsUTF8(PyObject_Repr(c->u->u_names))
);
Py_FatalError(buf);
} }
return scope; return scope;
@ -1930,7 +1927,7 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
else /* (reftype == FREE) */ else /* (reftype == FREE) */
arg = compiler_lookup_arg(c->u->u_freevars, name); arg = compiler_lookup_arg(c->u->u_freevars, name);
if (arg == -1) { if (arg == -1) {
fprintf(stderr, _Py_FatalErrorFormat(__func__,
"lookup %s in %s %d %d\n" "lookup %s in %s %d %d\n"
"freevars of %s: %s\n", "freevars of %s: %s\n",
PyUnicode_AsUTF8(PyObject_Repr(name)), PyUnicode_AsUTF8(PyObject_Repr(name)),
@ -1938,7 +1935,6 @@ compiler_make_closure(struct compiler *c, PyCodeObject *co, Py_ssize_t flags, Py
reftype, arg, reftype, arg,
PyUnicode_AsUTF8(co->co_name), PyUnicode_AsUTF8(co->co_name),
PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars))); PyUnicode_AsUTF8(PyObject_Repr(co->co_freevars)));
Py_FatalError("compiler_make_closure()");
} }
ADDOP_I(c, LOAD_CLOSURE, arg); ADDOP_I(c, LOAD_CLOSURE, arg);
} }
@ -5411,8 +5407,8 @@ stackdepth(struct compiler *c)
struct instr *instr = &b->b_instr[i]; struct instr *instr = &b->b_instr[i];
int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0); int effect = stack_effect(instr->i_opcode, instr->i_oparg, 0);
if (effect == PY_INVALID_STACK_EFFECT) { if (effect == PY_INVALID_STACK_EFFECT) {
fprintf(stderr, "opcode = %d\n", instr->i_opcode); _Py_FatalErrorFormat(__func__,
Py_FatalError("PyCompile_OpcodeStackEffect()"); "opcode = %d", instr->i_opcode);
} }
int new_depth = depth + effect; int new_depth = depth + effect;
if (new_depth > maxdepth) { if (new_depth > maxdepth) {

View File

@ -99,7 +99,7 @@ Py_FrozenMain(int argc, char **argv)
n = PyImport_ImportFrozenModule("__main__"); n = PyImport_ImportFrozenModule("__main__");
if (n == 0) if (n == 0)
Py_FatalError("__main__ not frozen"); Py_FatalError("the __main__ module is not frozen");
if (n < 0) { if (n < 0) {
PyErr_Print(); PyErr_Print();
sts = 1; sts = 1;

View File

@ -209,7 +209,7 @@ _PyImport_ReInitLock(void)
if (import_lock != NULL) { if (import_lock != NULL) {
import_lock = PyThread_allocate_lock(); import_lock = PyThread_allocate_lock();
if (import_lock == NULL) { if (import_lock == NULL) {
Py_FatalError("PyImport_ReInitLock failed to create a new lock"); _Py_FatalErrorFunc(__func__, "failed to create a new lock");
} }
} }
if (import_lock_level > 1) { if (import_lock_level > 1) {
@ -310,7 +310,7 @@ PyImport_GetModuleDict(void)
{ {
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE(); PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
if (interp->modules == NULL) { if (interp->modules == NULL) {
Py_FatalError("no module dictionary"); Py_FatalError("interpreter has no modules dictionary");
} }
return interp->modules; return interp->modules;
} }
@ -982,7 +982,7 @@ PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co,
_Py_IDENTIFIER(_get_sourcefile); _Py_IDENTIFIER(_get_sourcefile);
if (interp == NULL) { if (interp == NULL) {
Py_FatalError("no interpreter!"); Py_FatalError("no current interpreter");
} }
external= PyObject_GetAttrString(interp->importlib, external= PyObject_GetAttrString(interp->importlib,

View File

@ -81,12 +81,12 @@ PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
} }
len = vsprintf(buffer, format, va); len = vsprintf(buffer, format, va);
if (len < 0) if (len < 0) {
/* ignore the error */; /* ignore the error */;
}
else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) else if ((size_t)len >= size + _PyOS_vsnprintf_EXTRA_SPACE) {
Py_FatalError("Buffer overflow in PyOS_snprintf/PyOS_vsnprintf"); _Py_FatalErrorFunc(__func__, "Buffer overflow");
}
else { else {
const size_t to_copy = (size_t)len < size ? const size_t to_copy = (size_t)len < size ?
(size_t)len : size - 1; (size_t)len : size - 1;

View File

@ -484,6 +484,12 @@ pathconfig_global_init(void)
/* External interface */ /* External interface */
static void _Py_NO_RETURN
path_out_of_memory(const char *func)
{
_Py_FatalErrorFunc(func, "out of memory");
}
void void
Py_SetPath(const wchar_t *path) Py_SetPath(const wchar_t *path)
{ {
@ -515,7 +521,7 @@ Py_SetPath(const wchar_t *path)
|| _Py_path_config.exec_prefix == NULL || _Py_path_config.exec_prefix == NULL
|| _Py_path_config.module_search_path == NULL) || _Py_path_config.module_search_path == NULL)
{ {
Py_FatalError("out of memory"); path_out_of_memory(__func__);
} }
} }
@ -536,7 +542,7 @@ Py_SetPythonHome(const wchar_t *home)
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.home == NULL) { if (_Py_path_config.home == NULL) {
Py_FatalError("out of memory"); path_out_of_memory(__func__);
} }
} }
@ -557,7 +563,7 @@ Py_SetProgramName(const wchar_t *program_name)
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.program_name == NULL) { if (_Py_path_config.program_name == NULL) {
Py_FatalError("out of memory"); path_out_of_memory(__func__);
} }
} }
@ -577,7 +583,7 @@ _Py_SetProgramFullPath(const wchar_t *program_full_path)
PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
if (_Py_path_config.program_full_path == NULL) { if (_Py_path_config.program_full_path == NULL) {
Py_FatalError("out of memory"); path_out_of_memory(__func__);
} }
} }

View File

@ -2176,33 +2176,50 @@ fatal_error_dump_runtime(FILE *stream, _PyRuntimeState *runtime)
} }
static void _Py_NO_RETURN static inline void _Py_NO_RETURN
fatal_error(const char *prefix, const char *msg, int status) 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(FILE *stream, int header, const char *prefix, const char *msg,
int status)
{ {
FILE *stream = stderr;
const int fd = fileno(stream); const int fd = fileno(stream);
static int reentrant = 0; static int reentrant = 0;
if (reentrant) { if (reentrant) {
/* Py_FatalError() caused a second fatal error. /* Py_FatalError() caused a second fatal error.
Example: flush_std_files() raises a recursion error. */ Example: flush_std_files() raises a recursion error. */
goto exit; fatal_error_exit(status);
} }
reentrant = 1; reentrant = 1;
fprintf(stream, "Fatal Python error: "); if (header) {
if (prefix) { fprintf(stream, "Fatal Python error: ");
fputs(prefix, stream); if (prefix) {
fputs(": ", stream); fputs(prefix, stream);
fputs(": ", stream);
}
if (msg) {
fputs(msg, stream);
}
else {
fprintf(stream, "<message not set>");
}
fputs("\n", stream);
fflush(stream);
} }
if (msg) {
fputs(msg, stream);
}
else {
fprintf(stream, "<message not set>");
}
fputs("\n", stream);
fflush(stream); /* it helps in Windows debug build */
_PyRuntimeState *runtime = &_PyRuntime; _PyRuntimeState *runtime = &_PyRuntime;
fatal_error_dump_runtime(stream, runtime); fatal_error_dump_runtime(stream, runtime);
@ -2250,32 +2267,60 @@ fatal_error(const char *prefix, const char *msg, int status)
fatal_output_debug(msg); fatal_output_debug(msg);
#endif /* MS_WINDOWS */ #endif /* MS_WINDOWS */
exit: fatal_error_exit(status);
if (status < 0) {
#if defined(MS_WINDOWS) && defined(_DEBUG)
DebugBreak();
#endif
abort();
}
else {
exit(status);
}
} }
#undef Py_FatalError #undef Py_FatalError
void _Py_NO_RETURN void _Py_NO_RETURN
Py_FatalError(const char *msg) Py_FatalError(const char *msg)
{ {
fatal_error(NULL, msg, -1); fatal_error(stderr, 1, NULL, msg, -1);
} }
void _Py_NO_RETURN void _Py_NO_RETURN
_Py_FatalErrorFunc(const char *func, const char *msg) _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 void _Py_NO_RETURN
Py_ExitStatusException(PyStatus status) Py_ExitStatusException(PyStatus status)
{ {
@ -2283,7 +2328,7 @@ Py_ExitStatusException(PyStatus status)
exit(status.exitcode); exit(status.exitcode);
} }
else if (_PyStatus_IS_ERROR(status)) { 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 { else {
Py_FatalError("Py_ExitStatusException() must not be called on success"); Py_FatalError("Py_ExitStatusException() must not be called on success");

View File

@ -331,7 +331,7 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
PyInterpreterState **p; PyInterpreterState **p;
for (p = &interpreters->head; ; p = &(*p)->next) { for (p = &interpreters->head; ; p = &(*p)->next) {
if (*p == NULL) { if (*p == NULL) {
Py_FatalError("invalid interp"); Py_FatalError("NULL interpreter");
} }
if (*p == interp) { if (*p == interp) {
break; break;
@ -393,7 +393,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
HEAD_UNLOCK(runtime); HEAD_UNLOCK(runtime);
if (interpreters->head == NULL) { if (interpreters->head == NULL) {
Py_FatalError("missing main"); Py_FatalError("missing main interpreter");
} }
_PyThreadState_Swap(gilstate, tstate); _PyThreadState_Swap(gilstate, tstate);
} }
@ -686,7 +686,7 @@ int
PyState_AddModule(PyObject* module, struct PyModuleDef* def) PyState_AddModule(PyObject* module, struct PyModuleDef* def)
{ {
if (!def) { if (!def) {
Py_FatalError("Module Definition is NULL"); Py_FatalError("module definition is NULL");
return -1; return -1;
} }
@ -697,7 +697,7 @@ PyState_AddModule(PyObject* module, struct PyModuleDef* def)
index < PyList_GET_SIZE(interp->modules_by_index) && index < PyList_GET_SIZE(interp->modules_by_index) &&
module == PyList_GET_ITEM(interp->modules_by_index, index)) module == PyList_GET_ITEM(interp->modules_by_index, index))
{ {
Py_FatalError("Module already added"); _Py_FatalErrorFormat(__func__, "module %p already added", module);
return -1; return -1;
} }
return _PyState_AddModule(tstate, module, def); return _PyState_AddModule(tstate, module, def);
@ -715,7 +715,7 @@ PyState_RemoveModule(struct PyModuleDef* def)
} }
state = _PyInterpreterState_GET_UNSAFE(); state = _PyInterpreterState_GET_UNSAFE();
if (index == 0) { if (index == 0) {
Py_FatalError("Module index invalid"); Py_FatalError("invalid module index");
return -1; return -1;
} }
if (state->modules_by_index == NULL) { if (state->modules_by_index == NULL) {
@ -816,19 +816,23 @@ static void
tstate_delete_common(PyThreadState *tstate, tstate_delete_common(PyThreadState *tstate,
struct _gilstate_runtime_state *gilstate) struct _gilstate_runtime_state *gilstate)
{ {
_PyRuntimeState *runtime = tstate->interp->runtime;
ensure_tstate_not_null(__func__, tstate); ensure_tstate_not_null(__func__, tstate);
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
if (interp == NULL) { if (interp == NULL) {
Py_FatalError("NULL interp"); Py_FatalError("NULL interpreter");
} }
_PyRuntimeState *runtime = interp->runtime;
HEAD_LOCK(runtime); HEAD_LOCK(runtime);
if (tstate->prev) if (tstate->prev) {
tstate->prev->next = tstate->next; tstate->prev->next = tstate->next;
else }
else {
interp->tstate_head = tstate->next; interp->tstate_head = tstate->next;
if (tstate->next) }
if (tstate->next) {
tstate->next->prev = tstate->prev; tstate->next->prev = tstate->prev;
}
HEAD_UNLOCK(runtime); HEAD_UNLOCK(runtime);
if (gilstate->autoInterpreterState && if (gilstate->autoInterpreterState &&
@ -845,7 +849,7 @@ _PyThreadState_Delete(PyThreadState *tstate, int check_current)
struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate;
if (check_current) { if (check_current) {
if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) { if (tstate == _PyRuntimeGILState_GetThreadState(gilstate)) {
Py_FatalError("tstate is still current"); _Py_FatalErrorFormat(__func__, "tstate %p is still current", tstate);
} }
} }
tstate_delete_common(tstate, gilstate); tstate_delete_common(tstate, gilstate);
@ -1355,7 +1359,9 @@ PyGILState_Release(PyGILState_STATE oldstate)
by release-only users can't hurt. by release-only users can't hurt.
*/ */
if (!PyThreadState_IsCurrent(tstate)) { if (!PyThreadState_IsCurrent(tstate)) {
Py_FatalError("This thread state must be current when releasing"); _Py_FatalErrorFormat(__func__,
"thread state %p must be current when releasing",
tstate);
} }
assert(PyThreadState_IsCurrent(tstate)); assert(PyThreadState_IsCurrent(tstate));
--tstate->gilstate_counter; --tstate->gilstate_counter;