Added an explenation that the GIL can temporarily be released even while holding a GILGuard
This commit is contained in:
parent
db4a2d9017
commit
82129c70b4
|
@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||||
|
|
||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Added an explenation that the GIL can temporarily be released even while holding a GILGuard.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
* The pyobject_extract macro
|
* The pyobject_extract macro
|
||||||
|
|
|
@ -20,11 +20,30 @@ use typeob::{PyObjectAlloc, PyTypeInfo, PyTypeObject};
|
||||||
/// The 'Python' struct is a zero-size marker struct that is required for most Python operations.
|
/// The 'Python' struct is a zero-size marker struct that is required for most Python operations.
|
||||||
/// This is used to indicate that the operation accesses/modifies the Python interpreter state,
|
/// This is used to indicate that the operation accesses/modifies the Python interpreter state,
|
||||||
/// and thus can only be called if the Python interpreter is initialized and the
|
/// and thus can only be called if the Python interpreter is initialized and the
|
||||||
/// Python global interpreter lock (GIL) is acquired.
|
/// Python global interpreter lock (GIL) is acquired. The lifetime `'p` represents the lifetime of
|
||||||
/// The lifetime `'p` represents the lifetime of the Python interpreter.
|
/// the Python interpreter.
|
||||||
///
|
///
|
||||||
/// You can imagine the GIL to be a giant `Mutex<PythonInterpreterState>`.
|
/// Note that the GIL can be temporarily released by the python interpreter during a function call
|
||||||
/// The type `Python<'p>` then acts like a reference `&'p PythonInterpreterState`.
|
/// (e.g. importing a module), even when you're holding a GILGuard. In general, you don't need to
|
||||||
|
/// worry about this becauseas the GIL is reaquired before returning to the rust code:
|
||||||
|
///
|
||||||
|
/// ```text
|
||||||
|
/// GILGuard |=====================================|
|
||||||
|
/// GIL actually held |==========| |================|
|
||||||
|
/// Rust code running |=======| |==| |======|
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This behaviour can cause deadlocks when trying to lock while holding a GILGuard:
|
||||||
|
///
|
||||||
|
/// * Thread 1 acquires the GIL
|
||||||
|
/// * Thread 1 locks a mutex
|
||||||
|
/// * Thread 1 makes a call into the python interpreter, which releases the GIL
|
||||||
|
/// * Thread 2 acquires the GIL
|
||||||
|
/// * Thraed 2 tries to locks the mutex, blocks
|
||||||
|
/// * Thread 1's python interpreter call blocks trying to reacquire the GIL held by thread 2
|
||||||
|
///
|
||||||
|
/// To avoid deadlocking, you should release the GIL before trying to lock a mutex, e.g. with
|
||||||
|
/// [Python::allow_threads].
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
pub struct Python<'p>(PhantomData<&'p GILGuard>);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue