Repository navigation
GC crash _PyObject_AssertFailed with pdb #94215
Copy link
Copy link
Closed
Labels
3.11only security fixesonly security fixes3.12only security fixesonly security fixestype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
Reproducer:
def func():
print(
42
)
import pdb; pdb.set_trace()
func()Crash:
@kumaraditya303 ➜ /workspaces/cpython (main ✗) $ ./python main.py
> /workspaces/cpython/main.py(7)<module>()
-> func()
(Pdb) s
--Call--
> /workspaces/cpython/main.py(1)func()
-> def func():
(Pdb) n
> /workspaces/cpython/main.py(2)func()
-> print(
(Pdb) n
> /workspaces/cpython/main.py(3)func()
-> 42
(Pdb) j 1
> /workspaces/cpython/main.py(1)func()
-> def func():
(Pdb) exit
Traceback (most recent call last):
File "/workspaces/cpython/main.py", line 7, in <module>
func()
^^^^^^
File "/workspaces/cpython/main.py", line 1, in func
def func():
File "/workspaces/cpython/main.py", line 1, in func
def func():
File "/workspaces/cpython/Lib/bdb.py", line 90, in trace_dispatch
return self.dispatch_line(frame)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/workspaces/cpython/Lib/bdb.py", line 115, in dispatch_line
if self.quitting: raise BdbQuit
^^^^^^^^^^^^^
bdb.BdbQuit
Modules/gcmodule.c:113: gc_decref: Assertion "gc_get_refs(g) > 0" failed: refcount is too small
Enable tracemalloc to get the memory block allocation traceback
object address : 0x7f18ff3b81d0
object refcount : 2
object type : 0x55cfef2a6460
object type name: builtin_function_or_method
object repr : <built-in function print>
Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: finalizing (tstate=0x000055cfef3bca48)
Current thread 0x00007f18ff707280 (most recent call first):
Garbage-collecting
<no Python frame>
Aborted (core dumped)GDB stack trace (main)
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff7c71859 in __GI_abort () at abort.c:79
#2 0x000055555585db52 in fatal_error_exit (status=-1) at Python/pylifecycle.c:2614
#3 fatal_error (fd=2, header=header@entry=1, prefix=<optimized out>,
prefix@entry=0x55555594cd70 <__func__.19026> "_PyObject_AssertFailed", msg=<optimized out>,
msg@entry=0x55555594c575 "_PyObject_AssertFailed", status=status@entry=-1)
at Python/pylifecycle.c:2795
#4 0x000055555585dbb4 in _Py_FatalErrorFunc (
func=func@entry=0x55555594cd70 <__func__.19026> "_PyObject_AssertFailed",
msg=msg@entry=0x55555594c575 "_PyObject_AssertFailed") at Python/pylifecycle.c:2811
#5 0x00005555557431d2 in _PyObject_AssertFailed (
obj=obj@entry=<built-in method print of module object at remote 0x7ffff78f32f0>,
expr=expr@entry=0x5555559ab18c "gc_get_refs(g) > 0",
msg=msg@entry=0x55555594c5eb "refcount is too small",
file=file@entry=0x5555559ab11c "Modules/gcmodule.c", line=line@entry=113,
function=function@entry=0x5555559ab6c8 <__func__.18373> "gc_decref") at Objects/object.c:2360
#6 0x000055555588ad50 in gc_decref (g=0x7ffff79001c0) at Modules/gcmodule.c:116
#7 visit_decref (op=<built-in method print of module object at remote 0x7ffff78f32f0>,
parent=0x7ffff7900ad0) at Modules/gcmodule.c:459
#8 0x00005555557249a5 in dict_traverse (op=<optimized out>, visit=0x55555588ac96 <visit_decref>,
arg=0x7ffff7900ad0) at Objects/dictobject.c:3547
#9 0x000055555588a741 in subtract_refs (
containers=containers@entry=0x555555b869a8 <_PyRuntime+53896>) at Modules/gcmodule.c:478
#10 0x000055555588be95 in deduce_unreachable (unreachable=0x7fffffffc1d0,
base=0x555555b869a8 <_PyRuntime+53896>) at Modules/gcmodule.c:1100
#11 gc_collect_main (tstate=tstate@entry=0x555555ba0a48 <_PyRuntime+160552>,
generation=generation@entry=2, n_collected=n_collected@entry=0x7fffffffc258,
n_uncollectable=n_uncollectable@entry=0x7fffffffc260, nofail=nofail@entry=0)
at Modules/gcmodule.c:1226Python versions tested:
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
3.11only security fixesonly security fixes3.12only security fixesonly security fixestype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Projects
- StatusShow more project fieldsDone
Activity
tiran commentedon Jun 29, 2022
I can reproduce the issue in a pydebug build:
markshannon commentedon Jun 30, 2022
This might be related to #94438
tiran commentedon Jul 5, 2022
It's seems to be a ref counting issue. The jump and frame_setlineno seems to reduce the reference count by one. Please notice that the case without jump starts interpreter shutdown with
gc: 2, refcnt: 3. Withjump 1shutdown starts withgc: 1, refcnt: 2.ref counts without jump
ref counts with jump
debug hack
tiran commentedon Jul 5, 2022
The decref in
frame_stack_popseems to be the culprit. If I drop the decref, then pdb session no longer crashes. refleak checks fortest_frame test_code test_traceback test_pdbdo not show any refleaks either.iritkatriel commentedon Jul 5, 2022
I'm not sure how much that function is covered by tests. Can you verify whether it is?
tiran commentedon Jul 5, 2022
frame_stack_pop()is only used byframe_setlineno()conditionally. I guess it is not covered by any test case at all. Otherwise we would have seen crashers.pablogsal commentedon Jul 5, 2022
The issue may be a bit more general. Notice the jump is going back to the bytecode so we need to ensure that jumps and continues are always idempotent
23 remaining items
pythongh-94215: Fix reference count issue in exception_unwind
gh-94215: Fix error handling for line-tracing events (GH-94681)
[3.11] pythongh-94215: Fix error handling for line-tracing events (py…
[3.11] gh-94215: Fix error handling for line-tracing events (GH-94681) (
tiran commentedon Jul 8, 2022
Main branch and 3.11 branch are fixed. Older branches are not affected. This issue is no longer a release blocker. 🎉
I'm leaving the ticket open for @markshannon to verify the patch after he is back.
markshannon commentedon Jul 19, 2022
The changes look good to me.