Skip to content

Commit d53333b

Browse files
author
Mayank
committed
CoW replace_list: robustly clean referenced_blocks by identity; avoid stale indices and dead weakrefs (GH#62787)
1 parent 6464472 commit d53333b

File tree

1 file changed

+21
-16
lines changed

1 file changed

+21
-16
lines changed

pandas/core/internals/blocks.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -862,22 +862,27 @@ def replace_list(
862862
# This is ugly, but we have to get rid of intermediate refs. We
863863
# can simply clear the referenced_blocks if we already copied,
864864
# otherwise we have to remove ourselves
865-
# GH#62787: Handle invalid weak references properly
866-
self_blk_ids = {
867-
id(ref_block): i
868-
for i, b in enumerate(self.refs.referenced_blocks)
869-
if (ref_block := b()) is not None
870-
}
871-
for b in result:
872-
if b.refs is self.refs:
873-
# We are still sharing memory with self
874-
if id(b) in self_blk_ids:
875-
# Remove ourselves from the refs; we are temporary
876-
self.refs.referenced_blocks.pop(self_blk_ids[id(b)])
877-
else:
878-
# We have already copied, so we can clear the refs to avoid
879-
# future copies
880-
b.refs.referenced_blocks.clear()
865+
# GH#62787: Handle invalid weak references properly and robustly
866+
# Build a set of block ids from the current result that still share
867+
# the same refs object; those are temporary and should be removed
868+
# from referenced_blocks without relying on stale indices.
869+
to_remove_ids = {id(blk) for blk in result if blk.refs is self.refs}
870+
if to_remove_ids:
871+
# Keep only live weakrefs not pointing to blocks we remove
872+
new_refs = []
873+
for wr in self.refs.referenced_blocks:
874+
obj = wr()
875+
if obj is None:
876+
continue
877+
if id(obj) in to_remove_ids:
878+
continue
879+
new_refs.append(wr)
880+
self.refs.referenced_blocks = new_refs
881+
# For blocks that have already copied, clear their refs to avoid
882+
# future copies.
883+
for blk in result:
884+
if blk.refs is not self.refs:
885+
blk.refs.referenced_blocks.clear()
881886
new_rb.extend(result)
882887
rb = new_rb
883888
return rb

0 commit comments

Comments
 (0)