Skip to content

Commit

Permalink
new attempt
Browse files Browse the repository at this point in the history
  • Loading branch information
Ariel Ben-Yehuda committed Jan 27, 2025
1 parent abf1395 commit 996b1a5
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 72 deletions.
2 changes: 1 addition & 1 deletion pyo3-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ rust-version = "1.63"

[dependencies]
libc = "0.2.62"
rustversion = "1"

[features]

Expand Down Expand Up @@ -42,7 +43,6 @@ generate-import-lib = ["pyo3-build-config/python3-dll-a"]
paste = "1"

[build-dependencies]
cc = "1.2"
pyo3-build-config = { path = "../pyo3-build-config", version = "=0.23.3", features = ["resolve-config"] }

[lints]
Expand Down
15 changes: 0 additions & 15 deletions pyo3-ffi/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,6 @@ fn emit_link_config(interpreter_config: &InterpreterConfig) -> Result<()> {
Ok(())
}

fn do_cc(interpreter_config: &InterpreterConfig) {
let implementation_def = match interpreter_config.implementation {
PythonImplementation::CPython => "PYTHON_IS_CPYTHON",
PythonImplementation::PyPy => "PYTHON_IS_PYPY",
PythonImplementation::GraalPy => "PYTHON_IS_GRAALPY",
};
println!("cargo:rerun-if-changed=src/acquire_gil.cpp");
cc::Build::new()
.file("src/acquire_gil.c")
.define(implementation_def, None)
.compile("acquire_gil");
}

/// Prepares the PyO3 crate for compilation.
///
/// This loads the config from pyo3-build-config and then makes some additional checks to improve UX
Expand Down Expand Up @@ -231,8 +218,6 @@ fn configure_pyo3() -> Result<()> {
// Emit cfgs like `invalid_from_utf8_lint`
print_feature_cfgs();

do_cc(&interpreter_config);

Ok(())
}

Expand Down
48 changes: 0 additions & 48 deletions pyo3-ffi/src/acquire_gil.c

This file was deleted.

51 changes: 43 additions & 8 deletions pyo3-ffi/src/pystate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,50 @@ pub enum PyGILState_STATE {
PyGILState_UNLOCKED,
}

struct HangThread;

impl Drop for HangThread {
fn drop(&mut self) {
loop {
#[cfg(target_family = "unix")]
unsafe {
libc::pause();
}
#[cfg(not(target_family = "unix"))]
std::thread::sleep(std::time::Duration::from_secs(9_999_999));
}
}
}

// The PyGILState_Ensure function will call pthread_exit during interpreter shutdown,
// which causes undefined behavior. Redirect to the "safe" version that hangs instead,
// as Python 3.14 does.
//
// See https://github.com/rust-lang/rust/issues/135929

// C-unwind only supported (and necessary) since 1.71
mod raw {
#[rustversion::since(1.71)]
extern "C-unwind" {
#[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")]
pub fn PyGILState_Ensure() -> super::PyGILState_STATE;
}

#[rustversion::before(1.71)]
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure")]
pub fn PyGILState_Ensure() -> super::PyGILState_STATE;
}
}

pub unsafe extern "C" fn PyGILState_Ensure() -> PyGILState_STATE {
let guard = HangThread;
let ret: PyGILState_STATE = raw::PyGILState_Ensure();
std::mem::forget(guard);
ret
}

extern "C" {
// The PyGILState_Ensure function will call pthread_exit during interpreter shutdown,
// which causes undefined behavior. Redirect to the "safe" version that hangs instead,
// as Python 3.14 does.
//
// See https://github.com/rust-lang/rust/issues/135929
#[cfg_attr(PyPy, link_name = "PyPyGILState_Ensure_Safe")]
#[cfg_attr(not(PyPy), link_name = "PyGILState_Ensure_Safe")]
pub fn PyGILState_Ensure() -> PyGILState_STATE;
#[cfg_attr(PyPy, link_name = "PyPyGILState_Release")]
pub fn PyGILState_Release(arg1: PyGILState_STATE);
#[cfg(not(PyPy))]
Expand Down

0 comments on commit 996b1a5

Please sign in to comment.