Skip to content

Commit

Permalink
add test which is broken with gevent
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Dec 19, 2023
1 parent 1dca879 commit 7b82bbd
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 1 deletion.
1 change: 1 addition & 0 deletions pytests/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ classifiers = [

[project.optional-dependencies]
dev = [
"gevent>=23.9.1",
"hypothesis>=3.55",
"pytest-asyncio>=0.21",
"pytest-benchmark>=3.4",
Expand Down
12 changes: 11 additions & 1 deletion pytests/src/misc.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
use pyo3::prelude::*;
use pyo3::{prelude::*, types::PyDict};

#[pyfunction]
fn issue_219() {
// issue 219: acquiring GIL inside #[pyfunction] deadlocks.
Python::with_gil(|_| {});
}

#[pyfunction]
fn get_item_and_run_callback(dict: &PyDict, callback: &PyAny) -> PyResult<()> {
let item = dict.get_item("key")?.expect("key not found in dict");
let string = item.to_string();
callback.call0()?;
assert_eq!(item.to_string(), string);
Ok(())
}

#[pymodule]
pub fn misc(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(issue_219, m)?)?;
m.add_function(wrap_pyfunction!(get_item_and_run_callback, m)?)?;
Ok(())
}
38 changes: 38 additions & 0 deletions pytests/tests/test_misc.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from dataclasses import dataclass
import importlib
import platform
import sys

import gevent
import pyo3_pytests.misc
import pytest

Expand Down Expand Up @@ -48,3 +50,39 @@ def test_import_in_subinterpreter_forbidden():
)

_xxsubinterpreters.destroy(sub_interpreter)


class ArbitraryClass:
worker_id: int
iteration: int

def __init__(self, worker_id: int, iteration: int):
self.worker_id = worker_id
self.iteration = iteration

def __repr__(self):
return f"ArbitraryClass({self.worker_id}, {self.iteration})"

def __del__(self):
print("del", self.worker_id, self.iteration)


def test_gevent():
def worker(worker_id: int) -> None:
for iteration in range(2):
d = {"key": ArbitraryClass(worker_id, iteration)}

def arbitrary_python_code():
# remove the dictionary entry so that the class value can be
# garbage collected
del d["key"]
print("gevent sleep", worker_id, iteration)
gevent.sleep(0)
print("after gevent sleep", worker_id, iteration)

print("start", worker_id, iteration)
pyo3_pytests.misc.get_item_and_run_callback(d, arbitrary_python_code)
print("end", worker_id, iteration)

workers = [gevent.spawn(worker, i) for i in range(2)]
gevent.joinall(workers)
3 changes: 3 additions & 0 deletions src/gil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,9 @@ impl Drop for GILPool {
Vec::new()
}
});
println!("dropping: {:?}", unsafe {
std::mem::transmute::<_, &[&crate::PyAny]>(owned_objects.as_slice())
});
for obj in owned_objects {
unsafe {
ffi::Py_DECREF(obj.as_ptr());
Expand Down

0 comments on commit 7b82bbd

Please sign in to comment.