Skip to content

Commit 96907e3

Browse files
committed
Add GILGuard::check() for python3
Adds a function that returns true if the GIL is currently held for the current thread. PyGILState_Check() was only added in Python 3.4, so this doesn't support Python 2.7. When working with py.allow_threads(...) it is useful for the inner code to be able to verify the GIL is not held in case it needs to acquire the GIL on other threads. Being able to check this can help prevent accidental deadlocks. Ideally this could be done via static typing, similar to how the 'py' object ensures the GIL is held, but I couldn't think of a clever way to achieve this.
1 parent 8d94120 commit 96907e3

File tree

3 files changed

+11
-2
lines changed

3 files changed

+11
-2
lines changed

python27-sys/src/pystate.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl Clone for PyThreadState {
6060
}
6161

6262
#[repr(C)]
63-
#[derive(Copy, Clone)]
63+
#[derive(Copy, Clone, PartialEq)]
6464
pub enum PyGILState_STATE {
6565
PyGILState_LOCKED,
6666
PyGILState_UNLOCKED,

python3-sys/src/pystate.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ extern "C" {
5353
}
5454

5555
#[repr(C)]
56-
#[derive(Copy, Clone)]
56+
#[derive(Copy, Clone, PartialEq)]
5757
pub enum PyGILState_STATE {
5858
PyGILState_LOCKED,
5959
PyGILState_UNLOCKED,
@@ -62,6 +62,8 @@ pub enum PyGILState_STATE {
6262
#[cfg(any(Py_3_7, py_sys_config = "WITH_THREAD"))]
6363
#[cfg_attr(windows, link(name = "pythonXY"))]
6464
extern "C" {
65+
#[cfg(Py_3_4)]
66+
pub fn PyGILState_Check() -> PyGILState_STATE;
6567
pub fn PyGILState_Ensure() -> PyGILState_STATE;
6668
pub fn PyGILState_Release(arg1: PyGILState_STATE) -> ();
6769
pub fn PyGILState_GetThisThreadState() -> *mut PyThreadState;

src/pythonrun.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ impl GILGuard {
128128
pub fn python(&self) -> Python<'_> {
129129
unsafe { Python::assume_gil_acquired() }
130130
}
131+
132+
/// Checks if the current thread holds the GIL.
133+
#[cfg(Py_3_4)]
134+
pub fn check() -> bool {
135+
let gstate = unsafe { ffi::PyGILState_Check() };
136+
gstate == ffi::PyGILState_STATE::PyGILState_LOCKED
137+
}
131138
}
132139

133140
/// Mutex-like wrapper object for data that is protected by the Python GIL.

0 commit comments

Comments
 (0)