From 4afa994449f870a3cbf03abb126864005499ec40 Mon Sep 17 00:00:00 2001 From: Adam Reichold Date: Wed, 21 Jun 2023 09:12:10 +0200 Subject: [PATCH] Mark Python::with_pool as safe on stable. --- src/marker.rs | 71 +++------------------------------------------------ 1 file changed, 3 insertions(+), 68 deletions(-) diff --git a/src/marker.rs b/src/marker.rs index da592701..33bc987d 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -947,6 +947,9 @@ impl Python<'_> { /// it limits the closure to using the new GIL token at the cost of /// being unable to capture existing GIL-bound references. /// + /// Note that on stable Rust, this API suffers from the same the `SendWrapper` loophole + /// as [`allow_threads`][Self::allow_threads], c.f. the documentation of the [`Ungil`] trait, + /// /// # Examples /// /// ```rust @@ -989,7 +992,6 @@ impl Python<'_> { /// }); /// }); /// ``` - #[cfg(feature = "nightly")] #[inline] pub fn with_pool(&self, f: F) -> R where @@ -1002,73 +1004,6 @@ impl Python<'_> { f(pool.python()) } - - /// Creates a scope using a new pool for managing PyO3's owned references. - /// - /// This is a safer alterantive to [`new_pool`][Self::new_pool] as - /// it limits the closure to using the new GIL token at the cost of - /// being unable to capture existing GIL-bound references. - /// - /// # Examples - /// - /// ```rust - /// # use pyo3::prelude::*; - /// Python::with_gil(|py| { - /// // Some long-running process like a webserver, which never releases the GIL. - /// loop { - /// // Create a new scope, so that PyO3 can clear memory at the end of the loop. - /// unsafe { - /// py.with_pool(|py| { - /// // do stuff... - /// }); - /// } - /// # break; // Exit the loop so that doctest terminates! - /// } - /// }); - /// ``` - /// - /// The `Ungil` bound on the closure does prevent hanging on to existing GIL-bound references - /// - /// ```compile_fail - /// # use pyo3::prelude::*; - /// # use pyo3::types::PyString; - /// - /// Python::with_gil(|py| { - /// let old_str = PyString::new(py, "a message from the past"); - /// - /// py.with_pool(|_py| { - /// print!("{:?}", old_str); - /// }); - /// }); - /// ``` - /// - /// or continuing to use the old GIL token - /// - /// ```compile_fail - /// # use pyo3::prelude::*; - /// - /// Python::with_gil(|old_py| { - /// old_py.with_pool(|_new_py| { - /// let _none = old_py.None(); - /// }); - /// }); - /// ``` - /// - /// # Safety - /// - /// However, due to the `SendWrapper` loophole describe in the documentation of the [`Ungil`] trait, - /// this is still an unsafe API. Usage that does not involve runtime checking of thread affinity - /// should be practically safe. - #[cfg(not(feature = "nightly"))] - #[inline] - pub unsafe fn with_pool(&self, f: F) -> R - where - F: for<'py> FnOnce(Python<'py>) -> R + Ungil, - { - let pool = GILPool::new(); - - f(pool.python()) - } } impl<'unbound> Python<'unbound> {