Skip to content

Commit cc3fd09

Browse files
committed
Drop read lock before key_eq in dict get_hint
Move key_eq call outside the read lock guard to avoid potential deadlock when Python __eq__ re-enters dict mutation paths. Matches the existing pattern in lookup().
1 parent 0f044d6 commit cc3fd09

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

crates/vm/src/dict_inner.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -363,12 +363,19 @@ impl<T: Clone> Dict<T> {
363363
key: &K,
364364
hint: usize,
365365
) -> PyResult<Option<T>> {
366-
let inner = self.read();
367-
let Some(Some(entry)) = inner.entries.get(hint) else {
368-
return Ok(None);
366+
let (entry_key, entry_value) = {
367+
let inner = self.read();
368+
let Some(Some(entry)) = inner.entries.get(hint) else {
369+
return Ok(None);
370+
};
371+
if key.key_is(&entry.key) {
372+
return Ok(Some(entry.value.clone()));
373+
}
374+
(entry.key.clone(), entry.value.clone())
369375
};
370-
if key.key_is(&entry.key) || key.key_eq(vm, &entry.key)? {
371-
Ok(Some(entry.value.clone()))
376+
// key_eq may run Python __eq__, so must be outside the lock.
377+
if key.key_eq(vm, &entry_key)? {
378+
Ok(Some(entry_value))
372379
} else {
373380
Ok(None)
374381
}

0 commit comments

Comments
 (0)