Skip to content
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

avoid creating PyRef inside __traverse__ handler #4479

Merged
merged 1 commit into from
Aug 28, 2024

Conversation

davidhewitt
Copy link
Member

See #4265 (comment)

We cannot use PyRef<T> to guard access to the value inside a __traverse__ handler. Instead I use the PyClassObject<T> and manually perform the borrow checking.


/// Error returned by a `__traverse__` visitor implementation.
#[repr(transparent)]
pub struct PyTraverseError(pub(crate) c_int);
pub struct PyTraverseError(get_nonzero_c_int::TYPE);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit of a drive-by optimization, to add a niche for the 0.

/// Prevents the `PyVisit` from outliving the `__traverse__` call.
pub(crate) _guard: PhantomData<&'a ()>,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I completely removed the Python::assume_gil_acquired call from _call_traverse, so I needed to place a different reference back in for the lifetime. This is sufficient because the *mut c_void already prevents Send/Sync.

@davidhewitt
Copy link
Member Author

cc @ngoldbaum

@mejrs
Copy link
Member

mejrs commented Aug 24, 2024

We could also make the change suggested by the comment here....

#[repr(transparent)]
pub struct PyRef<'p, T: PyClass> {
    // TODO: once the GIL Ref API is removed, consider adding a lifetime parameter to `PyRef` to
    // store `Borrowed` here instead, avoiding reference counting overhead.
    inner: Bound<'p, T>,
}

as that would also avoid changing reference counts.

@Icxolu
Copy link
Contributor

Icxolu commented Aug 24, 2024

I believe that would need #4390. Also in that thread #4390 (comment) there was the suggestion to maybe delay that change to 0.24

@davidhewitt
Copy link
Member Author

Yes agreed, I considered changing PyRef but would prefer to delay given there's enough breaking changes coming in 0.23. I also want to be careful with changing PyRef right now because I think it might need other changes for the freethreaded build.

I also think I might backport this fix to 0.22, which would be another reason not to have the breaking change here.

@ngoldbaum
Copy link
Contributor

I did some local testing on this PR.

After rebasing on main to fix some noisy tests that were fixed by me last week, this does seem to fix the "accessing the GIL while a __traverse__ implementation is running" panics.

@davidhewitt
Copy link
Member Author

Great, will merge this. I am considering landing this as part of a stack of fixes in a 0.22.3 patch.

@davidhewitt davidhewitt added this pull request to the merge queue Aug 28, 2024
Merged via the queue into PyO3:main with commit 4689a35 Aug 28, 2024
43 checks passed
@davidhewitt davidhewitt deleted the traverse-no-pyref branch August 28, 2024 22:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants