Skip to content

test_gdb.test_jit.test_bt_unwinds_from_inside_jit_executor is fragile on aarch64 release builds #157965

Description

@johng

Bug report

Bug description:

Adding the following below to the Python/bytecodes.c caused test_bt_unwinds_from_inside_jit_executor to fail for me even though by itself it's a NOOP change.

Edit: At time of edit this test does not fail however I've referenced base commits where it has failed.

tier2 op(_GUARD_BUILTINS_IS_CANONICAL, (--)) {
    DEOPT_IF(BUILTINS() != tstate->interp->builtins);
}
Test Failure ``` ====================================================================== ERROR: test_bt_unwinds_from_inside_jit_executor (test.test_gdb.test_jit.JitBacktraceTests.test_bt_unwinds_from_inside_jit_executor) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/test_jit.py", line 199, in test_bt_unwinds_from_inside_jit_executor gdb_output = self.get_stack_trace( script=JIT_SAMPLE_SCRIPT, ...<5 lines>... PYTHON_JIT="1", ) File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/test_jit.py", line 88, in get_stack_trace return super().get_stack_trace(**kwargs) ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^ File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/util.py", line 265, in get_stack_trace out, err = run_gdb(*args, PYTHONHASHSEED=PYTHONHASHSEED, **env_vars) ~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/runner/work/cpython/cpython/Lib/test/test_gdb/util.py", line 88, in run_gdb raise Exception(f"{cmd_text} failed with exit code {proc.returncode}, " ...<2 lines>... f"stderr={stderr!r}") Exception: /usr/bin/gdb --batch -nx --init-eval-command 'add-auto-load-safe-path /home/runner/work/cpython/cpython/python-gdb.py' '--eval-command=set breakpoint pending yes' '--eval-command=break builtin_id' '--eval-command=set print address off' --eval-command=run '--eval-command=set print entry-values no' '--eval-command=python exec("import gdb\ntarget = '"'"'py::jit:executor'"'"'\nfor _ in range(20):\n frame = gdb.selected_frame()\n if frame is not None and frame.name() == target:\n break\n gdb.execute('"'"'finish'"'"')\nelse:\n raise RuntimeError('"'"'did not reach %s'"'"' % target)\n")' '--eval-command=python exec("import gdb\ntarget = '"'"'py::jit:executor'"'"'\nfor _ in range(4):\n frame = gdb.selected_frame()\n if frame is None or frame.name() != target:\n raise RuntimeError('"'"'left JIT region during stepping: '"'"'\n + repr(frame and frame.name()))\n gdb.execute('"'"'si'"'"')\nframe = gdb.selected_frame()\nif frame is None or frame.name() != target:\n raise RuntimeError('"'"'stepped out of JIT region after si'"'"')\n")' --eval-command=bt --args /home/runner/work/cpython/cpython/python -S /home/runner/work/cpython/cpython/Lib/test/test_gdb/gdb_jit_sample.py failed with exit code 1, expected exit code 0: stdout='Breakpoint 1 at 0x2b8e8c: file Python/clinic/bltinmodule.c.h, line 755.\n[Thread debugging using libthread_db enabled]\nUsing host libthread_db library "/usr/lib/aarch64-linux-gnu/libthread_db.so.1".\n\nBreakpoint 1, builtin_id (self=, v=42) at Python/clinic/bltinmodule.c.h:755\n755\t return_value = builtin_id_impl((PyModuleDef *)self, v);\n_PyObject_VectorcallTstate (tstate=<_PyRuntime+249576>, callable=, args=, nargsf=, kwnames=) at ./Include/internal/pycore_call.h:144\n144\t res = func(callable, args, nargsf, kwnames);\nValue returned is $1 = 187649991800368\n_Py_VectorCallInstrumentation_StackRefSteal (callable=187649991800368, arguments=, total_args=1, kwnames=0x0, call_instrumentation=false, frame=, this_instr=, tstate=) at Python/ceval.c:774\n774\t STACKREFS_TO_PYOBJECTS_CLEANUP(args_o);\n_PyEval_EvalFrameDefault (tstate=<_PyRuntime+249576>, frame=, throwflag=0) at Python/generated_cases.c.h:1916\n1916\t if (res_o == NULL) {\nValue returned is $2 = 187649991800368\n_PyEval_EvalFrame (tstate=<_PyRuntime+249576>, frame=, throwflag=0) at ./Include/internal/pycore_ceval.h:122\n122\t return _PyEval_EvalFrameDefault(tstate, frame, throwflag);\nValue returned is $3 = None\n[Inferior 1 (process 21431) exited normally]\n' stderr="Python Exception : No frame is currently selected.\nError occurred in Python: No frame is currently selected.\nPython Exception : No frame is currently selected.\nError occurred in Python: No frame is currently selected.\nNo stack.\n" ```

This caused #157766 to fail however recently this is passing again with the latest main from merge. Commit 212e6035133 is an example of where this fails, however recent changes to main do not fail any more.

From what I can tell with claude assistance this is related due to veneer being emitted.

Before, main snapshot (adrp at page offset 0xf7c, no veneer):
2d3f7c  adrp x0, <GOT page>        ; page address of the global offset table (GOT)
2d3f80  ldr  x0, [x0, #2392]       ; load &__stack_chk_guard from the GOT
2d3f84  ldr  x3, [sp, #120]        ; load the canary saved on this frame's stack
2d3f88  ldr  x2, [x0]              ; load the current guard value
2d3f8c  subs x3, x3, x2            ; compare; mismatch → __stack_chk_fail

After, + tier2 op (adrp at page offset 0x03c, patched):
2d403c  adrp x0, <GOT page>
2d4040  ldr  x0, [x0, #2408]
2d4044  ldr  x3, [sp, #120]
2d4048  b    e843419@…             ; ← ld replaced the 4th instruction
        ...
e843419@…:  ldr x2, [x0]           ;   the same load, relocated
            b   2d404c             ;   jump back to the subs

When we hit the vaneer it looks to break the gdb call tracking chaining so likely the test is catching a genuine bug. It seems to be fairly random if vaneer is emitted depending on the layout generated by the source code.

I added the AI analysis and some steps to reproducing in docker here

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Activity

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

    topic-JITtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions