FAILURE MAP
← Case archive

FA-90536 / Garbage collector invariants / Open access

Reference processing: finalizers run every cycle · case 01

An unreachable object with a finalizer is resurrected forever and never freed.

Verified by executionVariant 1 · 6 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Objects queued for finalization are never removed from the pending set.

THE FAILURE

Objects queued for finalization are never removed from the pending set.

Unsuccessful approach: Replacing the pending set with just the finalized objects re-queues exactly them next cycle.

Case contract

Each cycle: trace strong reachability from roots (weak and phantom references are not traced); weak references whose referent is not strongly reachable are cleared; pending finalizable objects that are not strongly reachable are queued for finalization once and resurrected together with everything they reach for this cycle; phantom references are enqueued only when their referent is not reachable even through the resurrected set; everything else is freed. Return per cycle the cleared weak refs, finalized objects, enqueued phantoms and freed objects.

Why this case matters

Reference-processing order decides whether code can observe resurrected or half-dead objects.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(heap, roots, weak, finalizable, phantom, cycles):
    heap = {k: list(v) for k, v in heap.items()}
    weak = {r: t for r, t in weak}
    phantom = {r: t for r, t in phantom}
    pending = set(finalizable)
    out = []
    def trace(starts, seen):
        stack = list(starts)
        while stack:
            o = stack.pop()
            if o is None or o in seen or o not in heap:
                continue
            seen.add(o)
            stack.extend(heap[o])
        return seen
    for _ in range(cycles):
        strong = trace(roots, set())
        to_final = sorted(o for o in pending if o not in strong and o in heap)
        reach = trace(to_final, set(strong))
        cleared = sorted(r for r, t in weak.items() if t is not None and t not in strong)
        for r in cleared:
            weak[r] = None
        pending = set(pending)
        enq = sorted(r for r, t in phantom.items() if t is not None and t not in reach)
        for r in enq:
            phantom[r] = None
        freed = sorted(o for o in heap if o not in reach)
        for o in freed:
            del heap[o]
        out.append({'weak': cleared, 'finalize': to_final, 'phantom': enq, 'freed': freed})
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: finalizable object over two cycles',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []},
    [11],
    [['w1', 13], ['w2', 12]],
    [13],
    [['p1', 14], ['p2', 16]],
    2),
   [{'finalize': [13], 'freed': [16], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [['w1', 13]], [13], [], 1),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [], [13], [], 3),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [13, 14, 15], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [], [13], [['p1', 15]], 1),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [], [13], [['p1', 14]], 2),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []},
    [11, 13, 16],
    [['w1', 13], ['w2', 12]],
    [13],
    [['p1', 14], ['p2', 16]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []},
    [21],
    [['w1', 23], ['w2', 22]],
    [23],
    [['p1', 24], ['p2', 26]],
    2),
   [{'finalize': [23], 'freed': [26], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [23, 24, 25], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [['w1', 23]], [23], [], 1),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [], [23], [], 3),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [23, 24, 25], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [], [23], [['p1', 25]], 1),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [], [23], [['p1', 24]], 2),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [23, 24, 25], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []},
    [21, 23, 26],
    [['w1', 23], ['w2', 22]],
    [23],
    [['p1', 24], ['p2', 26]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []},
    [31],
    [['w1', 33], ['w2', 32]],
    [33],
    [['p1', 34], ['p2', 36]],
    2),
   [{'finalize': [33], 'freed': [36], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [33, 34, 35], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [['w1', 33]], [33], [], 1),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [], [33], [], 3),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [33, 34, 35], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [], [33], [['p1', 35]], 1),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [], [33], [['p1', 34]], 2),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [33, 34, 35], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []},
    [31, 33, 36],
    [['w1', 33], ['w2', 32]],
    [33],
    [['p1', 34], ['p2', 36]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []},
    [41],
    [['w1', 43], ['w2', 42]],
    [43],
    [['p1', 44], ['p2', 46]],
    2),
   [{'finalize': [43], 'freed': [46], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [43, 44, 45], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [['w1', 43]], [43], [], 1),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [], [43], [], 3),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [43, 44, 45], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [], [43], [['p1', 45]], 1),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [], [43], [['p1', 44]], 2),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [43, 44, 45], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []},
    [41, 43, 46],
    [['w1', 43], ['w2', 42]],
    [43],
    [['p1', 44], ['p2', 46]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []},
    [51],
    [['w1', 53], ['w2', 52]],
    [53],
    [['p1', 54], ['p2', 56]],
    2),
   [{'finalize': [53], 'freed': [56], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [53, 54, 55], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [['w1', 53]], [53], [], 1),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [], [53], [], 3),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [53, 54, 55], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [], [53], [['p1', 55]], 1),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [], [53], [['p1', 54]], 2),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [53, 54, 55], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []},
    [51, 53, 56],
    [['w1', 53], ['w2', 52]],
    [53],
    [['p1', 54], ['p2', 56]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])]]
for label, args, expected in cases[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: finalizable object over two cycles[{'finalize': [13], 'freed': [16], 'phantom': ['p2'], 'weak': ['w1']}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': ['p2'], 'weak': ['w1']}, {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]Failed
weak reference to a resurrected object[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': ['w1']}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': ['w1']}]Passed
finalizer runs only once[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [13, 14, 15], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]Failed
children of a finalizable object stay alive[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}]Passed
phantom of an object only reachable from a finalizable one[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]Failed
control: all strongly reachable[{'finalize': [], 'freed': [], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [], 'freed': [], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]Passed

SHA-256 / 4eb0c8d683289029d269d8f713c5a41c1c394d2e00e4c2ea6d49adaa76adaec1

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(heap, roots, weak, finalizable, phantom, cycles):
    heap = {k: list(v) for k, v in heap.items()}
    weak = {r: t for r, t in weak}
    phantom = {r: t for r, t in phantom}
    pending = set(finalizable)
    out = []
    def trace(starts, seen):
        stack = list(starts)
        while stack:
            o = stack.pop()
            if o is None or o in seen or o not in heap:
                continue
            seen.add(o)
            stack.extend(heap[o])
        return seen
    for _ in range(cycles):
        strong = trace(roots, set())
        to_final = sorted(o for o in pending if o not in strong and o in heap)
        reach = trace(to_final, set(strong))
        cleared = sorted(r for r, t in weak.items() if t is not None and t not in strong)
        for r in cleared:
            weak[r] = None
        pending = set(to_final)
        enq = sorted(r for r, t in phantom.items() if t is not None and t not in reach)
        for r in enq:
            phantom[r] = None
        freed = sorted(o for o in heap if o not in reach)
        for o in freed:
            del heap[o]
        out.append({'weak': cleared, 'finalize': to_final, 'phantom': enq, 'freed': freed})
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: finalizable object over two cycles',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []},
    [11],
    [['w1', 13], ['w2', 12]],
    [13],
    [['p1', 14], ['p2', 16]],
    2),
   [{'finalize': [13], 'freed': [16], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [['w1', 13]], [13], [], 1),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [], [13], [], 3),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [13, 14, 15], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [], [13], [['p1', 15]], 1),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []}, [11], [], [13], [['p1', 14]], 2),
   [{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({11: [12], 12: [], 13: [14], 14: [15], 15: [], 16: []},
    [11, 13, 16],
    [['w1', 13], ['w2', 12]],
    [13],
    [['p1', 14], ['p2', 16]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []},
    [21],
    [['w1', 23], ['w2', 22]],
    [23],
    [['p1', 24], ['p2', 26]],
    2),
   [{'finalize': [23], 'freed': [26], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [23, 24, 25], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [['w1', 23]], [23], [], 1),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [], [23], [], 3),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [23, 24, 25], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [], [23], [['p1', 25]], 1),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []}, [21], [], [23], [['p1', 24]], 2),
   [{'finalize': [23], 'freed': [26], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [23, 24, 25], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({21: [22], 22: [], 23: [24], 24: [25], 25: [], 26: []},
    [21, 23, 26],
    [['w1', 23], ['w2', 22]],
    [23],
    [['p1', 24], ['p2', 26]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []},
    [31],
    [['w1', 33], ['w2', 32]],
    [33],
    [['p1', 34], ['p2', 36]],
    2),
   [{'finalize': [33], 'freed': [36], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [33, 34, 35], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [['w1', 33]], [33], [], 1),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [], [33], [], 3),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [33, 34, 35], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [], [33], [['p1', 35]], 1),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []}, [31], [], [33], [['p1', 34]], 2),
   [{'finalize': [33], 'freed': [36], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [33, 34, 35], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({31: [32], 32: [], 33: [34], 34: [35], 35: [], 36: []},
    [31, 33, 36],
    [['w1', 33], ['w2', 32]],
    [33],
    [['p1', 34], ['p2', 36]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []},
    [41],
    [['w1', 43], ['w2', 42]],
    [43],
    [['p1', 44], ['p2', 46]],
    2),
   [{'finalize': [43], 'freed': [46], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [43, 44, 45], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [['w1', 43]], [43], [], 1),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [], [43], [], 3),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [43, 44, 45], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [], [43], [['p1', 45]], 1),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []}, [41], [], [43], [['p1', 44]], 2),
   [{'finalize': [43], 'freed': [46], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [43, 44, 45], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({41: [42], 42: [], 43: [44], 44: [45], 45: [], 46: []},
    [41, 43, 46],
    [['w1', 43], ['w2', 42]],
    [43],
    [['p1', 44], ['p2', 46]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])],
 [('regression: finalizable object over two cycles',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []},
    [51],
    [['w1', 53], ['w2', 52]],
    [53],
    [['p1', 54], ['p2', 56]],
    2),
   [{'finalize': [53], 'freed': [56], 'phantom': ['p2'], 'weak': ['w1']},
    {'finalize': [], 'freed': [53, 54, 55], 'phantom': ['p1'], 'weak': []}]),
  ('weak reference to a resurrected object',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [['w1', 53]], [53], [], 1),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': ['w1']}]),
  ('finalizer runs only once',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [], [53], [], 3),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [53, 54, 55], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]),
  ('children of a finalizable object stay alive',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [], [53], [['p1', 55]], 1),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': []}]),
  ('phantom of an object only reachable from a finalizable one',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []}, [51], [], [53], [['p1', 54]], 2),
   [{'finalize': [53], 'freed': [56], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [53, 54, 55], 'phantom': ['p1'], 'weak': []}]),
  ('control: all strongly reachable',
   ({51: [52], 52: [], 53: [54], 54: [55], 55: [], 56: []},
    [51, 53, 56],
    [['w1', 53], ['w2', 52]],
    [53],
    [['p1', 54], ['p2', 56]],
    2),
   [{'finalize': [], 'freed': [], 'phantom': [], 'weak': []},
    {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}])]]
for label, args, expected in cases[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: finalizable object over two cycles[{'finalize': [13], 'freed': [16], 'phantom': ['p2'], 'weak': ['w1']}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': ['p2'], 'weak': ['w1']}, {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]Failed
weak reference to a resurrected object[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': ['w1']}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': ['w1']}]Passed
finalizer runs only once[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [13, 14, 15], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]Failed
children of a finalizable object stay alive[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}]Passed
phantom of an object only reachable from a finalizable one[{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [13], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [13], 'freed': [16], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [13, 14, 15], 'phantom': ['p1'], 'weak': []}]Failed
control: all strongly reachable[{'finalize': [], 'freed': [], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}][{'finalize': [], 'freed': [], 'phantom': [], 'weak': []}, {'finalize': [], 'freed': [], 'phantom': [], 'weak': []}]Passed

SHA-256 / 89fbec295cb65b11e1d91a99c72103e24b764177111040b5be1bf09b2635b61c

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 6 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic, bounded teaching model of one garbage-collector mechanism with stipulated rules; it is not a production collector and claims no conformance to any particular runtime. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:51:27.743441+00:00.

Case digest / f87e99d872bf7f2e11ad9f295ab22fecbae6be9a4981e7631bcf6cd0e0ca4a40