Skip to content

Commit 10cfe27

Browse files
committed
Fix occasional race condition in dictdatatype
1 parent 69aac59 commit 10cfe27

File tree

1 file changed

+14
-27
lines changed

1 file changed

+14
-27
lines changed

vm/src/dictdatatype.rs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@ impl<T> DictInner<T> {
215215
None
216216
}
217217
}
218+
219+
#[inline]
220+
fn get_entry_checked(&self, idx: EntryIndex, index_index: IndexIndex) -> Option<&DictEntry<T>> {
221+
match self.entries.get(idx) {
222+
Some(Some(entry)) if entry.index == index_index => Some(entry),
223+
_ => None,
224+
}
225+
}
218226
}
219227

220228
type PopInnerResult<T> = ControlFlow<Option<DictEntry<T>>>;
@@ -284,13 +292,8 @@ impl<T: Clone> Dict<T> {
284292
let (entry, index_index) = self.lookup(vm, key, hash, None)?;
285293
if let Some(index) = entry.index() {
286294
let inner = self.read();
287-
if let Some(entry) = inner.entries.get(index) {
288-
let entry = extract_dict_entry(entry);
289-
if entry.index == index_index {
290-
break Some(entry.value.clone());
291-
} else {
292-
// stuff shifted around, let's try again
293-
}
295+
if let Some(entry) = inner.get_entry_checked(index, index_index) {
296+
break Some(entry.value.clone());
294297
} else {
295298
// The dict was changed since we did lookup. Let's try again.
296299
continue;
@@ -395,13 +398,8 @@ impl<T: Clone> Dict<T> {
395398
let (index_entry, index_index) = lookup;
396399
if let Some(index) = index_entry.index() {
397400
let inner = self.read();
398-
if let Some(entry) = inner.entries.get(index) {
399-
let entry = extract_dict_entry(entry);
400-
if entry.index == index_index {
401-
break entry.value.clone();
402-
} else {
403-
// stuff shifted around, let's try again
404-
}
401+
if let Some(entry) = inner.get_entry_checked(index, index_index) {
402+
break entry.value.clone();
405403
} else {
406404
// The dict was changed since we did lookup, let's try again.
407405
continue;
@@ -439,13 +437,8 @@ impl<T: Clone> Dict<T> {
439437
let (index_entry, index_index) = lookup;
440438
if let Some(index) = index_entry.index() {
441439
let inner = self.read();
442-
if let Some(entry) = inner.entries.get(index) {
443-
let entry = extract_dict_entry(entry);
444-
if entry.index == index_index {
445-
break (entry.key.clone(), entry.value.clone());
446-
} else {
447-
// stuff shifted around, let's try again
448-
}
440+
if let Some(entry) = inner.get_entry_checked(index, index_index) {
441+
break (entry.key.clone(), entry.value.clone());
449442
} else {
450443
// The dict was changed since we did lookup, let's try again.
451444
continue;
@@ -886,12 +879,6 @@ fn str_exact<'a>(obj: &'a PyObject, vm: &VirtualMachine) -> Option<&'a PyStr> {
886879
}
887880
}
888881

889-
fn extract_dict_entry<T>(option_entry: &Option<DictEntry<T>>) -> &DictEntry<T> {
890-
option_entry
891-
.as_ref()
892-
.expect("The dict was changed since we did lookup.")
893-
}
894-
895882
#[cfg(test)]
896883
mod tests {
897884
use super::{Dict, DictKey};

0 commit comments

Comments
 (0)