Skip to content

gdb py-bt is no more compatible with Python 3.13+ #142095

Closed

Description

@cielavenir

Bug report

Bug description:

gdb ./python
r
Ctrl-C
py-bt
(gdb) py-bt
Traceback (most recent call first):
  (unable to read python frame information)

3.14.0b1 is affected and 3.14.0a7 is not affected.

Also I bisected git and found 1f5682f. And reverting it onto 3.14.0 fixes py-bt:

(gdb) py-bt
Traceback (most recent call first):
  File "/home/user/devel/cpython/Lib/_pyrepl/unix_console.py", line 439, in wait
    or bool(self.pollob.poll(timeout))
  File "/home/user/devel/cpython/Lib/_pyrepl/reader.py", line 703, in handle1
    self.console.wait(100)
  File "/home/user/devel/cpython/Lib/_pyrepl/reader.py", line 748, in readline
    self.handle1()
  File "/home/user/devel/cpython/Lib/_pyrepl/readline.py", line 395, in multiline_input
    return reader.readline()
  File "/home/user/devel/cpython/Lib/_pyrepl/simple_interact.py", line 143, in run_multiline_interactive_console
    statement = multiline_input(more_lines, ps1, ps2)
  File "/home/user/devel/cpython/Lib/_pyrepl/main.py", line 58, in interactive_console
    run_multiline_interactive_console(console)

This can be confirmed by building https://github.com/cielavenir/cpython/commits/3.14.0-pybt .

However I don't know why "reenabling autovectorization" fixes py-bt.

There is a similar report #127147 but this issue happens without --enable-optimizations.

Tested on Debian 13, GCC 14

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Activity

  1. cielavenir commented on Nov 29, 2025

    @cielavenir
    Author

    (let me repost in this thread)

    on 3.13, the affected commit is 5646f6f and you can try https://github.com/cielavenir/cpython/tree/3.13.9-pybt

    official version 3.13.3 is affected but 3.13.2 is not affected.

  2. changed the title [-][3.14] gdb py-bt does not work[/-] [+]gdb `py-bt` is no more compatible with Python 3.13+[/+] on Nov 29, 2025
  3. added
    interpreter-core(Objects, Python, Grammar, and Parser dirs)
    3.13only security fixes
    3.14bugs and security fixes
    3.15bugs and security fixes
    on Nov 29, 2025
  4. mpage commented on Nov 30, 2025

    @mpage
    Contributor

    I was able to reproduce this, but it's not clear to me what we should do about it. py-bt is failing because gcc is able to optimize the interpreter loop more effectively, which results in frame being optimized out:

    cpython/Tools/gdb/libpython.py

    Lines 1802 to 1805 in db098a4

    frame = self._gdbframe.read_var('frame')
    frame = PyFramePtr(frame)
    if not frame.is_optimized_out():
    return frame

    I don't think the current implementation of py-bt will work reliably when optimizations are enabled (we compile with -O3 when running ./configure without any additional arguments).

    A couple of options come to mind:

    1. Use stronger language recommending that the debug build be used. It's only recommended right now. py-bt works fine for me on debian 13/gcc 14 when Python is configured with --with-pydebug.
    2. Modify py-bt so that it uses a different approach to get the top-most frame. I think we might be able to read the current thread state from TLS and then grab the top-most frame from the thread state. That shouldn't be susceptible to compiler optimizations.
  5. cielavenir commented on Dec 1, 2025

    @cielavenir
    Author

    The thing is, we want RelWithDebInfo flavor of build...

    we might be able to read the current thread state from TLS

    I already tried this but it did not work

        def get_pyop(self):
            try:
                frame = self._gdbframe.read_var('frame')
                frame = PyFramePtr(frame)
                if not frame.is_optimized_out():
                    return frame
                tstate = self._gdbframe.read_var('tstate')
                if tstate is None:
                    return None
                frame = PyFramePtr(tstate.dereference()["current_frame"])
                if frame and not frame.is_optimized_out():
                    return frame
                return None
            except ValueError:
                raise # return None
  6. mpage commented on Dec 2, 2025

    @mpage
    Contributor

    I already tried this but it did not work

    What you have is reading tstate from the stack frame of the interpreter loop (and will potentially be affected in the same way as reading frame). I was suggesting reading the thread state from TLS, since that should be unaffected by compiler optimizations. Something like the following appears to work for me:

        def get_pyop(self):
            try:
                frame = self._gdbframe.read_var('frame')
                frame = PyFramePtr(frame)
                if not frame.is_optimized_out():
                    return frame
                gilstate = self._gdbframe.read_var('_Py_tss_gilstate')
                if gilstate is None:
                    return None
                frame = PyFramePtr(gilstate.dereference()["current_frame"])
                if frame:
                    return frame
                return None
            except ValueError:
                return None

    _Py_tss_gilstate is a TLS variable that stores the Python thread state associated with the current OS thread:

    cpython/Python/pystate.c

    Lines 75 to 77 in eb89286

    /* The "bound" thread state used by PyGILState_Ensure(),
    also known as a "gilstate." */
    _Py_thread_local PyThreadState *_Py_tss_gilstate = NULL;

  7. cielavenir commented on Dec 2, 2025

    @cielavenir
    Author

    @mpage Thank you but my test failed, _Py_tss_gilstate seems py3.15 only?

    edit: _Py_tss_tstate did not work either

  8. cielavenir commented on Dec 2, 2025

    @cielavenir
    Author

    b8998fe could be cherry-picked onto 3.14.0 without conflict, and your gdb update works, so I pushed https://github.com/cielavenir/cpython/tree/3.14.0-updategdb for reference

    edit: But I never know if such python build can load binary-wheel modules built for existing libpython3.14

  9. cielavenir commented on Dec 2, 2025

    @cielavenir
    Author

    However b8998fe cannot be cherry-picked onto 3.13.9 as it causes conflict.

  10. 7 remaining items

  11. vstinner commented on Dec 18, 2025

    @vstinner
    Member

    I think it's worth making py-bt work with -Og builds and release builds. That would save me a lot of time debugging crashes. Sometimes I get a coredump from a release or --with-pydebug build that's hard to reproduce. I end up having to manually examine _Py_tss_tstate or _Py_tss_gilstate to try to reconstruct the Python stack, which is painful and slow.

    I wrote the PR #142941 for that.

  12. added 2 commits that reference this issue on Jan 2, 2026
  13. colesbury commented on Jan 2, 2026

    @colesbury
    Contributor

    @vstinner - thanks! I adapted your PR and merged the logic back into the py-bt and py-bt-full commands:

    Still doing some more testing, but it seems to work in optimized builds as long as you don't strip the debug info out.

  14. cielavenir commented on Jan 3, 2026

    @cielavenir
    Author

    @colesbury thank you but this gdb.py did not work for me (it works when I apply cielavenir@21b8377 but the original issue is still there). What python versions will be compatible?

  15. cielavenir commented on Jan 3, 2026

    @cielavenir
    Author

    Btw I see this (with or without my hack patch)

    (gdb)  p ((PyCodeObject*)(_Py_tss_tstate->current_frame.f_executable.bits & ~1))->co_name
    Cannot access memory at address 0x48
    
  16. colesbury commented on Jan 5, 2026

    @colesbury
    Contributor

    @cielavenir please try the latest version of the PR. It should work with 3.13+

  17. added a commit that references this issue on Jan 8, 2026
  18. added a commit that references this issue on Jan 8, 2026
  19. added 3 commits that reference this issue on Jan 8, 2026
  20. added a commit that references this issue on Jan 12, 2026
  21. added a commit that references this issue on Feb 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.13only security fixes3.14bugs and security fixes3.15bugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions