python / cpython

The Python programming language
https://www.python.org
Other
63.33k stars 30.31k forks source link

GC aborts in debug no-gil build #126312

Open devdanzin opened 2 hours ago

devdanzin commented 2 hours ago

Crash report

What happened?

In debug no-gil builds with PYTHON_GIL=0, it's possible to trigger the three assertions here with simple code: https://github.com/python/cpython/blob/c84a136511c673f495f466887716b55c13b7e3ac/Python/gc_free_threading.c#L550-L558

For this code:

import gc
gc.freeze()
gc.is_finalized(lambda: None)
gc.collect()
gc.unfreeze()
gc.collect()

We get:

Python/gc_free_threading.c:550: validate_refcounts: Assertion "!gc_is_unreachable(op)" failed: object should not be marked as unreachable yet
Enable tracemalloc to get the memory block allocation traceback

object address  : 0x200007373f0
object refcount : 1152921504606846977
object type     : 0x55adadc26660
object type name: dict
object repr     : {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x20000330a20>, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/home/fusil/python-61/gc-assertion-abort-2/source.py', '__cached__': None, 'gc': <module 'gc' (built-in)>}

Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized

Current thread 0x00007f1b47a64740 (most recent call first):
  Garbage-collecting
  File "/home/fusil/python-61/gc-assertion-abort-2/source.py", line 6 in <module>
Aborted

For this code:

from threading import Thread
import gc

gc.freeze()
alive = [Thread(target=gc.freeze, args=())]
gc.collect()
gc.unfreeze()
gc.collect()

We get:

Python/gc_free_threading.c:554: validate_refcounts: Assertion "op->ob_tid == 0" failed: merged objects should have ob_tid == 0
Enable tracemalloc to get the memory block allocation traceback

object address  : 0x20000278210
object refcount : 1152921504606846994
object type     : 0x5616274befc0
object type name: type
object repr     : <class '_thread.lock'>

Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized

Current thread 0x00007f34ed160740 (most recent call first):
  Garbage-collecting
  File "/home/fusil/python-104/gc-abort-assertion/source.py", line 8 in <module>
Aborted

Lastly, for code I haven't minimized yet (but can, if it helps), we get:

Python/gc_free_threading.c:558: validate_refcounts: Assertion "op->ob_tid != 0" failed: unmerged objects should have ob_tid != 0
Enable tracemalloc to get the memory block allocation traceback

object address  : 0x200007980b0
object refcount : 1152921504606846980
object type     : 0x5637720b4f40
object type name: builtin_function_or_method
object repr     : <built-in function collect>

Fatal Python error: _PyObject_AssertFailed: _PyObject_AssertFailed
Python runtime state: initialized

Current thread 0x00007f63aef4c740 (most recent call first):
  Garbage-collecting
  File "/home/fusil/python-106/gc-abort-assertion-sigabrt-37/source.py", line 38 in callMethod
  File "/home/fusil/python-106/gc-abort-assertion-sigabrt-37/source.py", line 42 in callFunc
  File "/home/fusil/python-106/gc-abort-assertion-sigabrt-37/source.py", line 247 in <module>
Aborted

Found using fusil by @vstinner.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.14.0a1+ experimental free-threading build (heads/main:d467d9246c, Nov 1 2024, 09:05:56) [GCC 11.4.0]

ZeroIntensity commented 2 hours ago

Confirmed on the main branch and 3.13. Interestingly, this doesn't seem to happen on any other objects passed to is_finalized, and not even objects of the same type--only lambdas cause this. I did see that the reference count of a lambda is significantly high, but I'm guessing that's just a result of the DRC bits. I'm investigating to see what's going on.