Thanks for the analysis!
This is quite similar to issue793822: gc.get_referrers() can access unfinished tuples. The difference here is that what breaks is not the monitoring tool, but the "main" program!
Here is a simple script inspired from the original bug; PySequence_Tuple() uses PyTuple_SET_ITEM() which is a macro without the ob_refcnt check, but we can make it call _PyTuple_Resize() and fail there. All versions of CPython are affected:
import gc
TAG = object()
def monitor():
lst = [x for x in gc.get_referrers(TAG)
if isinstance(x, tuple)]
t = lst[0] # this *is* the result tuple
print(t) # full of nulls !
return t # Keep it alive for some time
def my_iter():
yield TAG # 'tag' gets stored in the result tuple
t = monitor()
for x in range(10):
yield x # SystemError when the tuple needs to be resized
tuple(my_iter()) |