From 9295f8122d366137c8cace79cf4b163f586028d3 Mon Sep 17 00:00:00 2001 From: Samuel Colvin Date: Fri, 24 Mar 2023 15:46:49 +0000 Subject: [PATCH] stop panic on to_string, report using write_unraisable instead --- newsfragments/3062.fixed.md | 1 + src/gil.rs | 8 ++++++++ src/marker.rs | 8 ++++++++ src/types/mod.rs | 11 +++++++++-- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 newsfragments/3062.fixed.md diff --git a/newsfragments/3062.fixed.md b/newsfragments/3062.fixed.md new file mode 100644 index 00000000000..9738978f7b4 --- /dev/null +++ b/newsfragments/3062.fixed.md @@ -0,0 +1 @@ +Stop panic on `fmt::Display`, instead return `""` string and report error via `sys.unraisablehook()` diff --git a/src/gil.rs b/src/gil.rs index aa4ed2e7825..5e3aa4d33ff 100644 --- a/src/gil.rs +++ b/src/gil.rs @@ -463,6 +463,14 @@ pub(crate) fn ensure_gil_unchecked() -> EnsureGIL { } } +/// Yields access to the GIL only if it is already held +pub(crate) fn try_ensure_gil() -> Option { + if gil_is_acquired() { + Some(EnsureGIL(None)) + } else { + None + } +} /// Struct used internally which avoids acquiring the GIL where it's not necessary. pub(crate) struct EnsureGIL(Option); diff --git a/src/marker.rs b/src/marker.rs index bd30d3c3396..7f93d27a1bc 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -354,6 +354,14 @@ impl Python<'_> { { f(gil::ensure_gil_unchecked().python()) } + + /// Similar to [`Self::with_gil`] but only provides access to the GIL if it is already held. + pub fn try_with_gil(f: F) -> Option + where + F: for<'py> FnOnce(Python<'py>) -> R, + { + gil::try_ensure_gil().map(|gil| f(unsafe { gil.python() })) + } } impl<'py> Python<'py> { diff --git a/src/types/mod.rs b/src/types/mod.rs index 8d3e2714383..235093dfa93 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -99,8 +99,15 @@ macro_rules! pyobject_native_type_base( fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> { - let s = self.str().or(::std::result::Result::Err(::std::fmt::Error))?; - f.write_str(&s.to_string_lossy()) + match self.str() { + ::std::result::Result::Ok(s) => return f.write_str(&s.to_string_lossy()), + ::std::result::Result::Err(err) => err.write_unraisable(self.py(), ::std::option::Option::Some(self)), + } + + match self.get_type().name() { + ::std::result::Result::Ok(name) => ::std::write!(f, "", name), + ::std::result::Result::Err(_err) => f.write_str(""), + } } }