-
Notifications
You must be signed in to change notification settings - Fork 792
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
Some more docs #2256
Some more docs #2256
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -806,22 +806,6 @@ impl<'py> Python<'py> { | |
err::error_on_minusone(self, v) | ||
} | ||
|
||
/// Retrieves a Python instance under the assumption that the GIL is already | ||
/// acquired at this point, and stays acquired for the lifetime `'py`. | ||
/// | ||
/// Because the output lifetime `'py` is not connected to any input parameter, | ||
/// care must be taken that the compiler infers an appropriate lifetime for `'py` | ||
/// when calling this function. | ||
/// | ||
/// # Safety | ||
/// | ||
/// The lifetime `'py` must be shorter than the period you *assume* that you have GIL. | ||
/// I.e., `Python<'static>` is always *really* unsafe. | ||
#[inline] | ||
pub unsafe fn assume_gil_acquired() -> Python<'py> { | ||
Python(PhantomData) | ||
} | ||
|
||
/// Create a new pool for managing PyO3's owned references. | ||
/// | ||
/// When this `GILPool` is dropped, all PyO3 owned references created after this `GILPool` will | ||
|
@@ -882,6 +866,29 @@ impl<'py> Python<'py> { | |
} | ||
} | ||
|
||
impl<'unbound> Python<'unbound> { | ||
/// Unsafely creates a Python token with an unbounded lifetime. | ||
/// | ||
/// Many of PyO3 APIs use `Python<'_>` as proof that the GIL is held, but this function can be | ||
/// used to call them unsafely. | ||
/// | ||
/// # Safety | ||
/// | ||
/// - This token and any borrowed Python references derived from it can only be safely used | ||
/// whilst the currently executing thread is actually holding the GIL. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re: threads, I was thinking about this: fn foo(py: Python<'_>){
let handle = std::thread::spawn(|| unsafe {
let py = Python::assume_gil_acquired();
// call some pyo3 apis
});
handle.join().unwrap();
} Is this legal? Should we declare that it is not allowed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As However, I would suggest not including this example in the documentation as it opens more questions than it answers IMHO and I think the current wording is the right thing to do in almost all of the cases. When someone has to handle a case where this is not so (as in your example), they should be sure enough to figure it out. Everybody else is probably just confused by watering down the statement about the current thread. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To clarify, the way I worded it would declare that it's not allowed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think the above is legal - holding the GIL on the Python side also sets a bunch of thread-local variables about the interpreter state. Not holding the GIL in the exact thread the Python API is called in will likely lead to segfaults by reading invalid values from these variables. |
||
/// - This function creates a token with an *unbounded* lifetime. Safe code can assume that | ||
/// holding a `Python<'py>` token means the GIL is and stays acquired for the lifetime `'py`. | ||
/// If you let it or borrowed Python references escape to safe code you are | ||
/// responsible for bounding the lifetime `'unbound` appropriately. For more on unbounded | ||
/// lifetimes, see the [nomicon]. | ||
/// | ||
/// [nomicon]: https://doc.rust-lang.org/nomicon/unbounded-lifetimes.html | ||
#[inline] | ||
pub unsafe fn assume_gil_acquired() -> Python<'unbound> { | ||
Python(PhantomData) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
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.
I've taken a liking to properly naming lifetimes as of recently. What would you think of renaming the
Python<'py>
lifetime toPython<'gil>
? It's still short and I think it represents the meaning of the lifetime better.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.
I agree with the sentiment, but I am not sure if the improvement is worth the churn?
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 should be a fairly mechanical change if we wanted to update. If we were consistent with always having
'gil
for the name of the GIL lifetime when present, that would also help make it clear when things did not depend on the GIL.