bpo-39882: Py_FatalError() logs the function name (GH-18819)

The Py_FatalError() function is replaced with a macro which logs
automatically the name of the current function, unless the
Py_LIMITED_API macro is defined.

Changes:

* Add _Py_FatalErrorFunc() function.
* Remove the function name from the message of Py_FatalError() calls
  which included the function name.
* Update tests.
This commit is contained in:
Victor Stinner 2020-03-07 00:54:20 +01:00 committed by GitHub
parent 7b3c252dc7
commit 9e5d30cc99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 112 additions and 69 deletions

View file

@ -388,6 +388,13 @@ Process Control
function :c:func:`abort` is called which will attempt to produce a :file:`core` function :c:func:`abort` is called which will attempt to produce a :file:`core`
file. file.
The ``Py_FatalError()`` function is replaced with a macro which logs
automatically the name of the current function, unless the
``Py_LIMITED_API`` macro is defined.
.. versionchanged:: 3.9
Log the function name automatically.
.. c:function:: void Py_Exit(int status) .. c:function:: void Py_Exit(int status)

View file

@ -178,6 +178,12 @@ PyAPI_FUNC(void) _PyErr_WriteUnraisableMsg(
const char *err_msg, const char *err_msg,
PyObject *obj); PyObject *obj);
PyAPI_FUNC(void) _Py_NO_RETURN _Py_FatalErrorFunc(
const char *func,
const char *message);
#define Py_FatalError(message) _Py_FatalErrorFunc(__func__, message)
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -21,7 +21,11 @@ PyAPI_FUNC(void) PyErr_GetExcInfo(PyObject **, PyObject **, PyObject **);
PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *); PyAPI_FUNC(void) PyErr_SetExcInfo(PyObject *, PyObject *, PyObject *);
#endif #endif
/* Defined in Python/pylifecycle.c */ /* Defined in Python/pylifecycle.c
The Py_FatalError() function is replaced with a macro which logs
automatically the name of the current function, unless the Py_LIMITED_API
macro is defined. */
PyAPI_FUNC(void) _Py_NO_RETURN Py_FatalError(const char *message); PyAPI_FUNC(void) _Py_NO_RETURN Py_FatalError(const char *message);
#if defined(Py_DEBUG) || defined(Py_LIMITED_API) #if defined(Py_DEBUG) || defined(Py_LIMITED_API)

View file

@ -197,7 +197,8 @@ class CAPITest(unittest.TestCase):
""") """)
rc, out, err = assert_python_failure('-c', code) rc, out, err = assert_python_failure('-c', code)
self.assertRegex(err.replace(b'\r', b''), self.assertRegex(err.replace(b'\r', b''),
br'Fatal Python error: a function returned NULL ' br'Fatal Python error: _Py_CheckFunctionResult: '
br'a function returned NULL '
br'without setting an error\n' br'without setting an error\n'
br'Python runtime state: initialized\n' br'Python runtime state: initialized\n'
br'SystemError: <built-in function ' br'SystemError: <built-in function '
@ -225,8 +226,9 @@ class CAPITest(unittest.TestCase):
""") """)
rc, out, err = assert_python_failure('-c', code) rc, out, err = assert_python_failure('-c', code)
self.assertRegex(err.replace(b'\r', b''), self.assertRegex(err.replace(b'\r', b''),
br'Fatal Python error: a function returned a ' br'Fatal Python error: _Py_CheckFunctionResult: '
br'result with an error set\n' br'a function returned a result '
br'with an error set\n'
br'Python runtime state: initialized\n' br'Python runtime state: initialized\n'
br'ValueError\n' br'ValueError\n'
br'\n' br'\n'
@ -668,7 +670,7 @@ class PyMemDebugTests(unittest.TestCase):
r"\n" r"\n"
r"Enable tracemalloc to get the memory block allocation traceback\n" r"Enable tracemalloc to get the memory block allocation traceback\n"
r"\n" r"\n"
r"Fatal Python error: bad trailing pad byte") r"Fatal Python error: _PyMem_DebugRawFree: bad trailing pad byte")
regex = regex.format(ptr=self.PTR_REGEX) regex = regex.format(ptr=self.PTR_REGEX)
regex = re.compile(regex, flags=re.DOTALL) regex = re.compile(regex, flags=re.DOTALL)
self.assertRegex(out, regex) self.assertRegex(out, regex)
@ -684,14 +686,14 @@ class PyMemDebugTests(unittest.TestCase):
r"\n" r"\n"
r"Enable tracemalloc to get the memory block allocation traceback\n" r"Enable tracemalloc to get the memory block allocation traceback\n"
r"\n" r"\n"
r"Fatal Python error: bad ID: Allocated using API 'm', verified using API 'r'\n") r"Fatal Python error: _PyMem_DebugRawFree: bad ID: Allocated using API 'm', verified using API 'r'\n")
regex = regex.format(ptr=self.PTR_REGEX) regex = regex.format(ptr=self.PTR_REGEX)
self.assertRegex(out, regex) self.assertRegex(out, regex)
def check_malloc_without_gil(self, code): def check_malloc_without_gil(self, code):
out = self.check(code) out = self.check(code)
expected = ('Fatal Python error: Python memory allocator called ' expected = ('Fatal Python error: _PyMem_DebugMalloc: '
'without holding the GIL') 'Python memory allocator called without holding the GIL')
self.assertIn(expected, out) self.assertIn(expected, out)
def test_pymem_malloc_without_gil(self): def test_pymem_malloc_without_gil(self):

View file

@ -1078,8 +1078,9 @@ class ExceptionTests(unittest.TestCase):
""" """
with SuppressCrashReport(): with SuppressCrashReport():
rc, out, err = script_helper.assert_python_failure("-c", code) rc, out, err = script_helper.assert_python_failure("-c", code)
self.assertIn(b'Fatal Python error: Cannot recover from ' self.assertIn(b'Fatal Python error: _PyErr_NormalizeException: '
b'MemoryErrors while normalizing exceptions.', err) b'Cannot recover from MemoryErrors while '
b'normalizing exceptions.', err)
@cpython_only @cpython_only
def test_MemoryError(self): def test_MemoryError(self):

View file

@ -123,7 +123,9 @@ class FaultHandlerTests(unittest.TestCase):
self.assertRegex(output, regex) self.assertRegex(output, regex)
self.assertNotEqual(exitcode, 0) self.assertNotEqual(exitcode, 0)
def check_fatal_error(self, code, line_number, name_regex, **kw): def check_fatal_error(self, code, line_number, name_regex, func=None, **kw):
if func:
name_regex = '%s: %s' % (func, name_regex)
fatal_error = 'Fatal Python error: %s' % name_regex fatal_error = 'Fatal Python error: %s' % name_regex
self.check_error(code, line_number, fatal_error, **kw) self.check_error(code, line_number, fatal_error, **kw)
@ -173,6 +175,7 @@ class FaultHandlerTests(unittest.TestCase):
3, 3,
'in new thread', 'in new thread',
know_current_thread=False, know_current_thread=False,
func='faulthandler_fatal_error_thread',
py_fatal_error=True) py_fatal_error=True)
def test_sigabrt(self): def test_sigabrt(self):
@ -230,6 +233,7 @@ class FaultHandlerTests(unittest.TestCase):
""", """,
2, 2,
'xyz', 'xyz',
func='faulthandler_fatal_error_py',
py_fatal_error=True) py_fatal_error=True)
def test_fatal_error_without_gil(self): def test_fatal_error_without_gil(self):
@ -239,6 +243,7 @@ class FaultHandlerTests(unittest.TestCase):
""", """,
2, 2,
'xyz', 'xyz',
func='faulthandler_fatal_error_py',
py_fatal_error=True) py_fatal_error=True)
@unittest.skipIf(sys.platform.startswith('openbsd'), @unittest.skipIf(sys.platform.startswith('openbsd'),

View file

@ -4247,7 +4247,8 @@ class CMiscIOTest(MiscIOTest):
err = res.err.decode() err = res.err.decode()
if res.rc != 0: if res.rc != 0:
# Failure: should be a fatal error # Failure: should be a fatal error
pattern = (r"Fatal Python error: could not acquire lock " pattern = (r"Fatal Python error: _enter_buffered_busy: "
r"could not acquire lock "
r"for <(_io\.)?BufferedWriter name='<{stream_name}>'> " r"for <(_io\.)?BufferedWriter name='<{stream_name}>'> "
r"at interpreter shutdown, possibly due to " r"at interpreter shutdown, possibly due to "
r"daemon threads".format_map(locals())) r"daemon threads".format_map(locals()))

View file

@ -269,6 +269,8 @@ class SysModuleTest(unittest.TestCase):
finally: finally:
sys.setrecursionlimit(oldlimit) sys.setrecursionlimit(oldlimit)
# The error message is specific to CPython
@test.support.cpython_only
def test_recursionlimit_fatalerror(self): def test_recursionlimit_fatalerror(self):
# A fatal error occurs if a second recursion limit is hit when recovering # A fatal error occurs if a second recursion limit is hit when recovering
# from a first one. # from a first one.
@ -290,7 +292,8 @@ class SysModuleTest(unittest.TestCase):
err = sub.communicate()[1] err = sub.communicate()[1]
self.assertTrue(sub.returncode, sub.returncode) self.assertTrue(sub.returncode, sub.returncode)
self.assertIn( self.assertIn(
b"Fatal Python error: Cannot recover from stack overflow", b"Fatal Python error: _Py_CheckRecursiveCall: "
b"Cannot recover from stack overflow",
err) err)
def test_getwindowsversion(self): def test_getwindowsversion(self):

View file

@ -0,0 +1,3 @@
The :c:func:`Py_FatalError` function is replaced with a macro which logs
automatically the name of the current function, unless the ``Py_LIMITED_API``
macro is defined.

View file

@ -25,7 +25,7 @@ static void* _PyMem_DebugRealloc(void *ctx, void *ptr, size_t size);
static void _PyMem_DebugFree(void *ctx, void *p); static void _PyMem_DebugFree(void *ctx, void *p);
static void _PyObject_DebugDumpAddress(const void *p); static void _PyObject_DebugDumpAddress(const void *p);
static void _PyMem_DebugCheckAddress(char api_id, const void *p); static void _PyMem_DebugCheckAddress(const char *func, char api_id, const void *p);
static void _PyMem_SetupDebugHooksDomain(PyMemAllocatorDomain domain); static void _PyMem_SetupDebugHooksDomain(PyMemAllocatorDomain domain);
@ -2205,7 +2205,7 @@ _PyMem_DebugRawFree(void *ctx, void *p)
uint8_t *q = (uint8_t *)p - 2*SST; /* address returned from malloc */ uint8_t *q = (uint8_t *)p - 2*SST; /* address returned from malloc */
size_t nbytes; size_t nbytes;
_PyMem_DebugCheckAddress(api->api_id, p); _PyMem_DebugCheckAddress(__func__, api->api_id, p);
nbytes = read_size_t(q); nbytes = read_size_t(q);
nbytes += PYMEM_DEBUG_EXTRA_BYTES; nbytes += PYMEM_DEBUG_EXTRA_BYTES;
memset(q, PYMEM_DEADBYTE, nbytes); memset(q, PYMEM_DEADBYTE, nbytes);
@ -2230,7 +2230,7 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
#define ERASED_SIZE 64 #define ERASED_SIZE 64
uint8_t save[2*ERASED_SIZE]; /* A copy of erased bytes. */ uint8_t save[2*ERASED_SIZE]; /* A copy of erased bytes. */
_PyMem_DebugCheckAddress(api->api_id, p); _PyMem_DebugCheckAddress(__func__, api->api_id, p);
data = (uint8_t *)p; data = (uint8_t *)p;
head = data - 2*SST; head = data - 2*SST;
@ -2314,10 +2314,11 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
} }
static inline void static inline void
_PyMem_DebugCheckGIL(void) _PyMem_DebugCheckGIL(const char *func)
{ {
if (!PyGILState_Check()) { if (!PyGILState_Check()) {
Py_FatalError("Python memory allocator called " _Py_FatalErrorFunc(func,
"Python memory allocator called "
"without holding the GIL"); "without holding the GIL");
} }
} }
@ -2325,14 +2326,14 @@ _PyMem_DebugCheckGIL(void)
static void * static void *
_PyMem_DebugMalloc(void *ctx, size_t nbytes) _PyMem_DebugMalloc(void *ctx, size_t nbytes)
{ {
_PyMem_DebugCheckGIL(); _PyMem_DebugCheckGIL(__func__);
return _PyMem_DebugRawMalloc(ctx, nbytes); return _PyMem_DebugRawMalloc(ctx, nbytes);
} }
static void * static void *
_PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize) _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize)
{ {
_PyMem_DebugCheckGIL(); _PyMem_DebugCheckGIL(__func__);
return _PyMem_DebugRawCalloc(ctx, nelem, elsize); return _PyMem_DebugRawCalloc(ctx, nelem, elsize);
} }
@ -2340,7 +2341,7 @@ _PyMem_DebugCalloc(void *ctx, size_t nelem, size_t elsize)
static void static void
_PyMem_DebugFree(void *ctx, void *ptr) _PyMem_DebugFree(void *ctx, void *ptr)
{ {
_PyMem_DebugCheckGIL(); _PyMem_DebugCheckGIL(__func__);
_PyMem_DebugRawFree(ctx, ptr); _PyMem_DebugRawFree(ctx, ptr);
} }
@ -2348,7 +2349,7 @@ _PyMem_DebugFree(void *ctx, void *ptr)
static void * static void *
_PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes) _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
{ {
_PyMem_DebugCheckGIL(); _PyMem_DebugCheckGIL(__func__);
return _PyMem_DebugRawRealloc(ctx, ptr, nbytes); return _PyMem_DebugRawRealloc(ctx, ptr, nbytes);
} }
@ -2358,7 +2359,7 @@ _PyMem_DebugRealloc(void *ctx, void *ptr, size_t nbytes)
* The API id, is also checked. * The API id, is also checked.
*/ */
static void static void
_PyMem_DebugCheckAddress(char api, const void *p) _PyMem_DebugCheckAddress(const char *func, char api, const void *p)
{ {
const uint8_t *q = (const uint8_t *)p; const uint8_t *q = (const uint8_t *)p;
char msgbuf[64]; char msgbuf[64];
@ -2406,7 +2407,7 @@ _PyMem_DebugCheckAddress(char api, const void *p)
error: error:
_PyObject_DebugDumpAddress(p); _PyObject_DebugDumpAddress(p);
Py_FatalError(msg); _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

@ -54,8 +54,9 @@ s_push(stack *s, const dfa *d, node *parent)
static void static void
s_pop(stack *s) s_pop(stack *s)
{ {
if (s_empty(s)) if (s_empty(s)) {
Py_FatalError("s_pop: parser stack underflow -- FATAL"); Py_FatalError("parser stack underflow");
}
s->s_top++; s->s_top++;
} }

View file

@ -1031,12 +1031,14 @@ static void
tok_backup(struct tok_state *tok, int c) 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("tok_backup: beginning of buffer"); Py_FatalError("beginning of buffer");
if (*tok->cur != c) }
if (*tok->cur != c) {
*tok->cur = c; *tok->cur = c;
} }
} }
}
static int static int

View file

@ -283,7 +283,7 @@ PyEval_AcquireLock(void)
struct _ceval_runtime_state *ceval = &runtime->ceval; struct _ceval_runtime_state *ceval = &runtime->ceval;
PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime); PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
if (tstate == NULL) { if (tstate == NULL) {
Py_FatalError("PyEval_AcquireLock: current thread state is NULL"); Py_FatalError("current thread state is NULL");
} }
take_gil(ceval, tstate); take_gil(ceval, tstate);
exit_thread_if_finalizing(tstate); exit_thread_if_finalizing(tstate);
@ -314,7 +314,7 @@ PyEval_AcquireThread(PyThreadState *tstate)
take_gil(ceval, tstate); take_gil(ceval, tstate);
exit_thread_if_finalizing(tstate); exit_thread_if_finalizing(tstate);
if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) {
Py_FatalError("PyEval_AcquireThread: non-NULL old thread state"); Py_FatalError("non-NULL old thread state");
} }
} }
@ -326,7 +326,7 @@ PyEval_ReleaseThread(PyThreadState *tstate)
_PyRuntimeState *runtime = tstate->interp->runtime; _PyRuntimeState *runtime = tstate->interp->runtime;
PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); PyThreadState *new_tstate = _PyThreadState_Swap(&runtime->gilstate, NULL);
if (new_tstate != tstate) { if (new_tstate != tstate) {
Py_FatalError("PyEval_ReleaseThread: wrong thread state"); Py_FatalError("wrong thread state");
} }
drop_gil(&runtime->ceval, tstate); drop_gil(&runtime->ceval, tstate);
} }
@ -373,7 +373,7 @@ PyEval_SaveThread(void)
struct _ceval_runtime_state *ceval = &runtime->ceval; struct _ceval_runtime_state *ceval = &runtime->ceval;
PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL); PyThreadState *tstate = _PyThreadState_Swap(&runtime->gilstate, NULL);
if (tstate == NULL) { if (tstate == NULL) {
Py_FatalError("PyEval_SaveThread: NULL tstate"); Py_FatalError("NULL tstate");
} }
assert(gil_created(&ceval->gil)); assert(gil_created(&ceval->gil));
drop_gil(ceval, tstate); drop_gil(ceval, tstate);
@ -1236,7 +1236,7 @@ main_loop:
if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) { if (_Py_atomic_load_relaxed(&ceval->gil_drop_request)) {
/* Give another thread a chance */ /* Give another thread a chance */
if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) { if (_PyThreadState_Swap(&runtime->gilstate, NULL) != tstate) {
Py_FatalError("ceval: tstate mix-up"); Py_FatalError("tstate mix-up");
} }
drop_gil(ceval, tstate); drop_gil(ceval, tstate);
@ -1248,7 +1248,7 @@ main_loop:
exit_thread_if_finalizing(tstate); exit_thread_if_finalizing(tstate);
if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) { if (_PyThreadState_Swap(&runtime->gilstate, tstate) != NULL) {
Py_FatalError("ceval: orphan tstate"); Py_FatalError("orphan tstate");
} }
} }
/* Check for asynchronous exceptions. */ /* Check for asynchronous exceptions. */

View file

@ -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("PyImport_GetModuleDict: no module dictionary!"); Py_FatalError("no module dictionary");
} }
return interp->modules; return interp->modules;
} }
@ -982,8 +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("PyImport_ExecCodeModuleWithPathnames: " Py_FatalError("no interpreter!");
"no interpreter!");
} }
external= PyObject_GetAttrString(interp->importlib, external= PyObject_GetAttrString(interp->importlib,

View file

@ -515,7 +515,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("Py_SetPath() failed: out of memory"); Py_FatalError("out of memory");
} }
} }
@ -536,7 +536,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("Py_SetPythonHome() failed: out of memory"); Py_FatalError("out of memory");
} }
} }
@ -557,7 +557,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("Py_SetProgramName() failed: out of memory"); Py_FatalError("out of memory");
} }
} }
@ -577,7 +577,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("_Py_SetProgramFullPath() failed: out of memory"); Py_FatalError("out of memory");
} }
} }

View file

@ -1611,10 +1611,10 @@ Py_EndInterpreter(PyThreadState *tstate)
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
if (tstate != _PyThreadState_GET()) { if (tstate != _PyThreadState_GET()) {
Py_FatalError("Py_EndInterpreter: thread is not current"); Py_FatalError("thread is not current");
} }
if (tstate->frame != NULL) { if (tstate->frame != NULL) {
Py_FatalError("Py_EndInterpreter: thread still has a frame"); Py_FatalError("thread still has a frame");
} }
interp->finalizing = 1; interp->finalizing = 1;
@ -1624,7 +1624,7 @@ Py_EndInterpreter(PyThreadState *tstate)
call_py_exitfuncs(tstate); call_py_exitfuncs(tstate);
if (tstate != interp->tstate_head || tstate->next != NULL) { if (tstate != interp->tstate_head || tstate->next != NULL) {
Py_FatalError("Py_EndInterpreter: not the last thread"); Py_FatalError("not the last thread");
} }
_PyImport_Cleanup(tstate); _PyImport_Cleanup(tstate);
@ -2241,12 +2241,20 @@ exit:
} }
} }
#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(NULL, msg, -1);
} }
void _Py_NO_RETURN
_Py_FatalErrorFunc(const char *func, const char *msg)
{
fatal_error(func, msg, -1);
}
void _Py_NO_RETURN void _Py_NO_RETURN
Py_ExitStatusException(PyStatus status) Py_ExitStatusException(PyStatus status)
{ {

View file

@ -327,20 +327,20 @@ 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("PyInterpreterState_Delete: invalid interp"); Py_FatalError("invalid interp");
} }
if (*p == interp) { if (*p == interp) {
break; break;
} }
} }
if (interp->tstate_head != NULL) { if (interp->tstate_head != NULL) {
Py_FatalError("PyInterpreterState_Delete: remaining threads"); Py_FatalError("remaining threads");
} }
*p = interp->next; *p = interp->next;
if (interpreters->main == interp) { if (interpreters->main == interp) {
interpreters->main = NULL; interpreters->main = NULL;
if (interpreters->head != NULL) { if (interpreters->head != NULL) {
Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); Py_FatalError("remaining subinterpreters");
} }
} }
HEAD_UNLOCK(runtime); HEAD_UNLOCK(runtime);
@ -363,7 +363,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL); PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL);
if (tstate != NULL && tstate->interp != interpreters->main) { if (tstate != NULL && tstate->interp != interpreters->main) {
Py_FatalError("PyInterpreterState_DeleteExceptMain: not main interpreter"); Py_FatalError("not main interpreter");
} }
HEAD_LOCK(runtime); HEAD_LOCK(runtime);
@ -389,7 +389,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime)
HEAD_UNLOCK(runtime); HEAD_UNLOCK(runtime);
if (interpreters->head == NULL) { if (interpreters->head == NULL) {
Py_FatalError("PyInterpreterState_DeleteExceptMain: missing main"); Py_FatalError("missing main");
} }
_PyThreadState_Swap(gilstate, tstate); _PyThreadState_Swap(gilstate, tstate);
} }
@ -400,11 +400,11 @@ _PyInterpreterState_Get(void)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (tstate == NULL) { if (tstate == NULL) {
Py_FatalError("_PyInterpreterState_Get(): no current thread state"); Py_FatalError("no current thread state");
} }
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
if (interp == NULL) { if (interp == NULL) {
Py_FatalError("_PyInterpreterState_Get(): no current interpreter"); Py_FatalError("no current interpreter");
} }
return interp; return interp;
} }
@ -695,7 +695,7 @@ int
PyState_AddModule(PyObject* module, struct PyModuleDef* def) PyState_AddModule(PyObject* module, struct PyModuleDef* def)
{ {
if (!def) { if (!def) {
Py_FatalError("PyState_AddModule: Module Definition is NULL"); Py_FatalError("Module Definition is NULL");
return -1; return -1;
} }
@ -706,7 +706,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("PyState_AddModule: Module already added!"); Py_FatalError("Module already added");
return -1; return -1;
} }
return _PyState_AddModule(tstate, module, def); return _PyState_AddModule(tstate, module, def);
@ -724,15 +724,15 @@ PyState_RemoveModule(struct PyModuleDef* def)
} }
state = _PyInterpreterState_GET_UNSAFE(); state = _PyInterpreterState_GET_UNSAFE();
if (index == 0) { if (index == 0) {
Py_FatalError("PyState_RemoveModule: Module index invalid."); Py_FatalError("Module index invalid");
return -1; return -1;
} }
if (state->modules_by_index == NULL) { if (state->modules_by_index == NULL) {
Py_FatalError("PyState_RemoveModule: Interpreters module-list not accessible."); Py_FatalError("Interpreters module-list not accessible.");
return -1; return -1;
} }
if (index > PyList_GET_SIZE(state->modules_by_index)) { if (index > PyList_GET_SIZE(state->modules_by_index)) {
Py_FatalError("PyState_RemoveModule: Module index out of bounds."); Py_FatalError("Module index out of bounds.");
return -1; return -1;
} }
Py_INCREF(Py_None); Py_INCREF(Py_None);
@ -819,11 +819,11 @@ tstate_delete_common(PyThreadState *tstate,
{ {
_PyRuntimeState *runtime = tstate->interp->runtime; _PyRuntimeState *runtime = tstate->interp->runtime;
if (tstate == NULL) { if (tstate == NULL) {
Py_FatalError("PyThreadState_Delete: NULL tstate"); Py_FatalError("NULL tstate");
} }
PyInterpreterState *interp = tstate->interp; PyInterpreterState *interp = tstate->interp;
if (interp == NULL) { if (interp == NULL) {
Py_FatalError("PyThreadState_Delete: NULL interp"); Py_FatalError("NULL interp");
} }
HEAD_LOCK(runtime); HEAD_LOCK(runtime);
if (tstate->prev) if (tstate->prev)
@ -850,7 +850,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("PyThreadState_Delete: tstate is still current"); Py_FatalError("tstate is still current");
} }
} }
tstate_delete_common(tstate, gilstate); tstate_delete_common(tstate, gilstate);
@ -869,9 +869,9 @@ _PyThreadState_DeleteCurrent(_PyRuntimeState *runtime)
{ {
struct _gilstate_runtime_state *gilstate = &runtime->gilstate; struct _gilstate_runtime_state *gilstate = &runtime->gilstate;
PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate); PyThreadState *tstate = _PyRuntimeGILState_GetThreadState(gilstate);
if (tstate == NULL) if (tstate == NULL) {
Py_FatalError( Py_FatalError("no current tstate");
"PyThreadState_DeleteCurrent: no current tstate"); }
tstate_delete_common(tstate, gilstate); tstate_delete_common(tstate, gilstate);
_PyRuntimeGILState_SetThreadState(gilstate, NULL); _PyRuntimeGILState_SetThreadState(gilstate, NULL);
PyEval_ReleaseLock(); PyEval_ReleaseLock();
@ -932,9 +932,9 @@ PyThreadState *
PyThreadState_Get(void) PyThreadState_Get(void)
{ {
PyThreadState *tstate = _PyThreadState_GET(); PyThreadState *tstate = _PyThreadState_GET();
if (tstate == NULL) if (tstate == NULL) {
Py_FatalError("PyThreadState_Get: no current thread"); Py_FatalError("no current thread");
}
return tstate; return tstate;
} }