From c95258c98d15bab317ca8955fbfca37df30da655 Mon Sep 17 00:00:00 2001 From: Fabian Freyer Date: Mon, 20 Feb 2023 22:56:51 +0100 Subject: [PATCH 1/3] Implement UnwindSafe by never returning on panic Don't return objects to the pool on panic, since we can't be sure whether they were the source of the panic. See-also: #139 --- src/managed/mod.rs | 15 +++++++++++++++ src/unmanaged/mod.rs | 7 +++++++ 2 files changed, 22 insertions(+) diff --git a/src/managed/mod.rs b/src/managed/mod.rs index d6ebd4e3..97178d7a 100644 --- a/src/managed/mod.rs +++ b/src/managed/mod.rs @@ -71,6 +71,7 @@ use std::{ future::Future, marker::PhantomData, ops::{Deref, DerefMut}, + panic::{RefUnwindSafe, UnwindSafe}, sync::{ atomic::{AtomicUsize, Ordering}, Arc, Mutex, Weak, @@ -615,6 +616,20 @@ impl>> Pool { } } +impl>> UnwindSafe for Pool +where + M: UnwindSafe, + W: UnwindSafe, +{ +} + +impl>> RefUnwindSafe for Pool +where + M: UnwindSafe, + W: UnwindSafe, +{ +} + struct PoolInner { manager: M, slots: Mutex>>, diff --git a/src/unmanaged/mod.rs b/src/unmanaged/mod.rs index 7b899322..a6f6f219 100644 --- a/src/unmanaged/mod.rs +++ b/src/unmanaged/mod.rs @@ -78,6 +78,13 @@ impl Object { impl Drop for Object { fn drop(&mut self) { + // If we're panicking, there is no way to determine whether the object + // we are dropping is the source of the panic. Therefore, always discard + // the object on a panic, and do not return it to the pool. + if std::thread::panicking() { + return; + } + if let Some(obj) = self.obj.take() { if let Some(pool) = self.pool.upgrade() { { From 5b6cf55fc1ce8e48233235f633484a24ac0a0e1e Mon Sep 17 00:00:00 2001 From: Fabian Freyer Date: Tue, 21 Feb 2023 00:16:23 +0100 Subject: [PATCH 2/3] postgres: Manager is UnwindSafe --- postgres/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/postgres/src/lib.rs b/postgres/src/lib.rs index bb716933..a44c565b 100644 --- a/postgres/src/lib.rs +++ b/postgres/src/lib.rs @@ -154,6 +154,8 @@ impl managed::Manager for Manager { } } +impl std::panic::UnwindSafe for Manager {} + #[async_trait] trait Connect: Sync + Send { async fn connect(&self, pg_config: &PgConfig) -> Result<(PgClient, JoinHandle<()>), Error>; From e001940aa3a90c1a9a7b398f53d3d187466c9f32 Mon Sep 17 00:00:00 2001 From: Fabian Freyer Date: Tue, 21 Feb 2023 00:16:55 +0100 Subject: [PATCH 3/3] Unwind Safety: Don't require for W --- src/managed/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/managed/mod.rs b/src/managed/mod.rs index 97178d7a..3a300467 100644 --- a/src/managed/mod.rs +++ b/src/managed/mod.rs @@ -619,14 +619,12 @@ impl>> Pool { impl>> UnwindSafe for Pool where M: UnwindSafe, - W: UnwindSafe, { } impl>> RefUnwindSafe for Pool where M: UnwindSafe, - W: UnwindSafe, { }