Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PYTHONMALLOCSTATS=1 fails with fatal error at Python exit #111499

Closed
vstinner opened this issue Oct 30, 2023 · 4 comments
Closed

PYTHONMALLOCSTATS=1 fails with fatal error at Python exit #111499

vstinner opened this issue Oct 30, 2023 · 4 comments
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes topic-subinterpreters type-bug An unexpected behavior, bug, or error

Comments

@vstinner
Copy link
Member

vstinner commented Oct 30, 2023

Py_FinalizeEx() calls _PyObject_DebugMallocStats() which calls indirectly _PyInterpreterState_GET(). Problem: at this point, there is no "interpreter" anymore, and so _PyInterpreterState_GET() fails with a fatal error.

It's a regression introduced by commit df3173d. Python 3.12 is also affected.

Reproducer:

$ PYTHONMALLOCSTATS=1 ./python -c pass
Small block threshold = 512, in 32 size classes.
(...)
Total                              =              262,144

Small block threshold = 512, in 32 size classes.
(...)
Total                              =              655,360

Fatal Python error: _PyInterpreterState_GET: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL)
Python runtime state: finalizing (tstate=0x0000000000ae7550)

Abandon (core dumped)

cc @ericsnowcurrently

Linked PRs

@vstinner vstinner added 3.12 bugs and security fixes 3.13 bugs and security fixes labels Oct 30, 2023
@vstinner
Copy link
Member Author

Apparently, nobody cares nor uses this feature which has no test. I just close the issue. I don't have the bandwidth to work on a fix.

@ShahriyarR
Copy link

Not sure if this is the related information or not, added here for future reference.
I got the same error with Python 3.12 while doing some tests.
Compiled Python as described here:
https://devguide.python.org/

Test:

$ gdb python

(gdb) break main
(gdb) call PyLong_FromLong(22222)
Fatal Python error: _PyInterpreterState_GET: the function must be called with the GIL held, after Python initialization and before Python finalization, but the GIL is released (the current Python thread state is NULL)
Python runtime state: unknown

Basically, the fix is calling Py_Initialize() before:

(gdb) call Py_Initialize()

The difference is, in Python 3.9 I got sissegv instead of this Fatal error.

@ericsnowcurrently ericsnowcurrently added type-bug An unexpected behavior, bug, or error topic-subinterpreters labels Feb 27, 2024
@devdanzin
Copy link
Contributor

Apparently, nobody cares nor uses this feature which has no test. I just close the issue. I don't have the bandwidth to work on a fix.

I'm trying to add a test as part of #120006, but having segfaults (Linux) or non-zero process exit codes (Windows) is kinda getting in the way. Could this issue be reopened so other devs can attempt to solve it?

It seems the error has changed between versions:

Python 3.12.3 (Linux), non-debug build:

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7ac632a in _PyInterpreterState_GET () at ./Include/internal/pycore_pystate.h:133
133         return tstate->interp;

Python 3.14.0a0 (heads/main:6e012ced6c) (Linux), non-debug build:

Program received signal SIGSEGV, Segmentation fault.
0x00005555556b0e3c in get_state () at Objects/obmalloc.c:1368
1368        return interp->obmalloc;

The fix might be as simple as (pardon my C):

diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index 4fe195b631..04e24bd407 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -3266,6 +3266,15 @@ py_mimalloc_print_stats(FILE *out)
 static void
 pymalloc_print_stats(FILE *out)
 {
+    PyThreadState *tstate = _PyThreadState_GET();
+    if (tstate == NULL || tstate->interp == NULL) {
+        return;
+    }
+
+    PyInterpreterState *interp = _PyInterpreterState_GET();
+    if (interp == NULL || interp->obmalloc == NULL) {
+        return;
+    }
     OMState *state = get_state();

     uint i;

vstinner added a commit to vstinner/cpython that referenced this issue Jun 4, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
vstinner added a commit to vstinner/cpython that referenced this issue Jun 4, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
@vstinner
Copy link
Member Author

vstinner commented Jun 4, 2024

I wrote PR gh-120021 to fix the issue.

vstinner added a commit that referenced this issue Jun 4, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
miss-islington pushed a commit to miss-islington/cpython that referenced this issue Jun 4, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
(cherry picked from commit 5a1205b)

Co-authored-by: Victor Stinner <[email protected]>
vstinner added a commit to vstinner/cpython that referenced this issue Jun 4, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.

(cherry picked from commit 5a1205b)
vstinner added a commit that referenced this issue Jun 4, 2024
…0023)

gh-111499: Fix PYTHONMALLOCSTATS at Python exit (#120021)

Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.

(cherry picked from commit 5a1205b)
vstinner added a commit that referenced this issue Jun 4, 2024
…120022)

gh-111499: Fix PYTHONMALLOCSTATS at Python exit (GH-120021)

Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
(cherry picked from commit 5a1205b)

Co-authored-by: Victor Stinner <[email protected]>
barneygale pushed a commit to barneygale/cpython that referenced this issue Jun 5, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
noahbkim pushed a commit to hudson-trading/cpython that referenced this issue Jul 11, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
estyxx pushed a commit to estyxx/cpython that referenced this issue Jul 17, 2024
Call _PyObject_DebugMallocStats() earlier in Py_FinalizeEx(), before
the interpreter is deleted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 bugs and security fixes 3.13 bugs and security fixes topic-subinterpreters type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

4 participants