-
Notifications
You must be signed in to change notification settings - Fork 784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix PyDict issues on free-threaded build #4788
Conversation
src/types/dict.rs
Outdated
@@ -470,15 +478,15 @@ impl DictIterImpl { | |||
let mut key: *mut ffi::PyObject = std::ptr::null_mut(); | |||
let mut value: *mut ffi::PyObject = std::ptr::null_mut(); | |||
|
|||
if unsafe { ffi::PyDict_Next(dict.as_ptr(), ppos, &mut key, &mut value) } != 0 { | |||
if ffi::PyDict_Next(dict.as_ptr(), ppos, &mut key, &mut value) != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO we should keep these unsafe
blocks. unsafe_op_in_unsafe_fn
will be warn be default in the 2024 edition and it makes it easier validate and document the safety invariants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! For some reason I thought there was a clippy lint to remove these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like Rust 1.63 objects:
https://github.com/PyO3/pyo3/actions/runs/12571738722/job/35043025705#step:11:107
Is there a way to keep this with the "unnecessary" unsafes and still compile on older rust?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could add a #[deny(unsafe_op_in_unsafe_fn)]
on the function. Not the nicest solution I guess but it should work.
b6d1d36
to
9b42a6d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
* clarify safety docs for PyDict API * get dict size using PyDict_Size on free-threaded build * avoid unnecessary critical sections in PyDict * add changelog entry * fix build error on GIL-enabled build * address code review comments * move attribute below doc comment * ignore unsafe_op_in_unsafe_fn in next_unchecked --------- Co-authored-by: David Hewitt <[email protected]>
* clarify safety docs for PyDict API * get dict size using PyDict_Size on free-threaded build * avoid unnecessary critical sections in PyDict * add changelog entry * fix build error on GIL-enabled build * address code review comments * move attribute below doc comment * ignore unsafe_op_in_unsafe_fn in next_unchecked --------- Co-authored-by: David Hewitt <[email protected]>
This fixes two issues with PyDict on the free-threaded build.
We were acquiring an inner critical section in
next()
in functions where we had already acquired an outer critical section. That is unnecessary. I've renamedDictIterImpl::DictIter::next
tonext_unchecked
, marked itunsafe
, and systematically used it in spots where we already had a critical section acquired. In the only spot we didn't, I manually added a critical section. I think having an unsafenext_unchecked
is easier to reason about - you need to do the locking yourself.We were accessing dict internals in a thread-unsafe manner, we should go through the C API on the free-threaded build. CPython uses a relaxed atomic load internally.
Also includes some minor doc improvements.
This should probably be backported to the 0.23 branch.
ping @bschoenmaeckers