Skip to content

Commit

Permalink
Copy dict on free-threaded builds to prevent concurrent modifications
Browse files Browse the repository at this point in the history
  • Loading branch information
bschoenmaeckers committed Sep 3, 2024
1 parent ae0ee72 commit afab9b2
Showing 1 changed file with 5 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/types/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,6 @@ pub enum BoundDictIterator<'py> {
/// Iterator over the items of the dictionary, using the C-API `PyDict_Next`. This variant is
/// only used when the dictionary is an exact instance of `PyDict` and the GIL enabled.
#[allow(missing_docs)]
#[cfg(not(Py_GIL_DISABLED))]
DictIter {
dict: Bound<'py, PyDict>,
ppos: ffi::Py_ssize_t,
Expand All @@ -402,7 +401,6 @@ impl<'py> Iterator for BoundDictIterator<'py> {
(key, value)
})
}
#[cfg(not(Py_GIL_DISABLED))]
BoundDictIterator::DictIter {
dict,
ppos,
Expand Down Expand Up @@ -466,7 +464,6 @@ impl<'py> ExactSizeIterator for BoundDictIterator<'py> {
fn len(&self) -> usize {
match self {
BoundDictIterator::ItemIter { remaining, .. } => *remaining as usize,
#[cfg(not(Py_GIL_DISABLED))]
BoundDictIterator::DictIter { remaining, .. } => *remaining as usize,
}
}
Expand All @@ -476,8 +473,12 @@ impl<'py> BoundDictIterator<'py> {
fn new(dict: Bound<'py, PyDict>) -> Self {
let remaining = dict_len(&dict);

#[cfg(not(Py_GIL_DISABLED))]
if dict.is_exact_instance_of::<PyDict>() {
// Copy the dictionary if the GIL is disabled, as we can't guarantee that the dictionary
// won't be modified during iteration.
#[cfg(Py_GIL_DISABLED)]
let dict = dict.copy().unwrap();

return BoundDictIterator::DictIter {
dict,
ppos: 0,
Expand Down

0 comments on commit afab9b2

Please sign in to comment.