pyo3_pytests/
misc.rs

1use pyo3::{
2    prelude::*,
3    types::{PyDict, PyString},
4};
5
6#[pyfunction]
7fn issue_219() {
8    // issue 219: acquiring GIL inside #[pyfunction] deadlocks.
9    Python::with_gil(|_| {});
10}
11
12#[pyclass]
13struct LockHolder {
14    #[allow(unused)]
15    // Mutex needed for the MSRV
16    sender: std::sync::Mutex<std::sync::mpsc::Sender<()>>,
17}
18
19// This will hammer the GIL once the LockHolder is dropped.
20#[pyfunction]
21fn hammer_gil_in_thread() -> LockHolder {
22    let (sender, receiver) = std::sync::mpsc::channel();
23    std::thread::spawn(move || {
24        receiver.recv().ok();
25        // now the interpreter has shut down, so hammer the GIL. In buggy
26        // versions of PyO3 this will cause a crash.
27        loop {
28            Python::with_gil(|_py| ());
29        }
30    });
31    LockHolder {
32        sender: std::sync::Mutex::new(sender),
33    }
34}
35
36#[pyfunction]
37fn get_type_fully_qualified_name<'py>(obj: &Bound<'py, PyAny>) -> PyResult<Bound<'py, PyString>> {
38    obj.get_type().fully_qualified_name()
39}
40
41#[pyfunction]
42fn accepts_bool(val: bool) -> bool {
43    val
44}
45
46#[pyfunction]
47fn get_item_and_run_callback(dict: Bound<'_, PyDict>, callback: Bound<'_, PyAny>) -> PyResult<()> {
48    // This function gives the opportunity to run a pure-Python callback so that
49    // gevent can instigate a context switch. This had problematic interactions
50    // with PyO3's removed "GIL Pool".
51    // For context, see https://github.com/PyO3/pyo3/issues/3668
52    let item = dict.get_item("key")?.expect("key not found in dict");
53    let string = item.to_string();
54    callback.call0()?;
55    assert_eq!(item.to_string(), string);
56    Ok(())
57}
58
59#[pymodule(gil_used = false)]
60pub fn misc(m: &Bound<'_, PyModule>) -> PyResult<()> {
61    m.add_function(wrap_pyfunction!(issue_219, m)?)?;
62    m.add_function(wrap_pyfunction!(hammer_gil_in_thread, m)?)?;
63    m.add_function(wrap_pyfunction!(get_type_fully_qualified_name, m)?)?;
64    m.add_function(wrap_pyfunction!(accepts_bool, m)?)?;
65    m.add_function(wrap_pyfunction!(get_item_and_run_callback, m)?)?;
66    Ok(())
67}
⚠️ Internal Docs ⚠️ Not Public API 👉 Official Docs Here