mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Fix store subscr list finalizer deadlock (#8956)
* Release replaced list item outside the lock in STORE_SUBSCR_LIST_INT Assisted-by: Claude Code:claude-opus-5-5 * Add a snippet for finalizers reading a list during a specialized store Assisted-by: Claude Code:claude-opus-5-5
This commit is contained in:
1 parent
f39b054b9c
commit
7536730ed6
2 files changed
+35
-1
No files matched your search
@@ -6430,7 +6430,11 @@ impl ExecutingFrame<'_> {
|
||||
{
|
||||
let mut vec = list.borrow_vec_mut();
|
||||
if i < vec.len() {
|
||||
vec[i] = value;
|
||||
// Unlock before dropping the replaced element; its
|
||||
// finalizer may access this list.
|
||||
let old = core::mem::replace(&mut vec[i], value);
|
||||
drop(vec);
|
||||
drop(old);
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,3 +342,33 @@ def module_attribute_custom_dict_key():
|
||||
|
||||
|
||||
module_attribute_custom_dict_key()
|
||||
|
||||
|
||||
## STORE_SUBSCR_LIST_INT: the replaced element's finalizer can read the list
|
||||
|
||||
|
||||
def store_subscr_list_int_finalizer_reads_list():
|
||||
target = [None]
|
||||
seen = []
|
||||
|
||||
class Item:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def __del__(self):
|
||||
seen.append((self.value, len(target), target[0] is self))
|
||||
|
||||
def store(value):
|
||||
target[0] = value
|
||||
|
||||
for i in range(300):
|
||||
store(Item(i))
|
||||
assert any(
|
||||
op.opname == "STORE_SUBSCR_LIST_INT"
|
||||
for op in dis.get_instructions(store, adaptive=True)
|
||||
)
|
||||
store(None)
|
||||
assert seen == [(i, 1, False) for i in range(300)]
|
||||
|
||||
|
||||
store_subscr_list_int_finalizer_reads_list()
|
||||
Reference in new issue
Block a user