Skip to content

Commit 3086626

Browse files
committed
fix: Fix a panic when calling JoinError::into_panic.
That's a lot of panics. This patch fixes a panic raised by `JoinError:into_panic` when the `JoinError` represents a cancellation instead of a panic.
1 parent 245bc2c commit 3086626

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

crates/deadpool-runtime/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ tokio_1 = { package = "tokio", version = "1.0", features = [
3535
"time",
3636
"rt",
3737
], optional = true }
38+
39+
[dev-dependencies]
40+
tokio_1 = { package = "tokio", version = "1.0", features = ["rt", "macros"] }

crates/deadpool-runtime/src/lib.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,13 @@ impl Runtime {
8989
{
9090
match self {
9191
#[cfg(feature = "tokio_1")]
92-
Self::Tokio1 => tokio_1::task::spawn_blocking(f)
93-
.await
94-
.map_err(|e| SpawnBlockingError::Panic(e.into_panic())),
92+
Self::Tokio1 => tokio_1::task::spawn_blocking(f).await.map_err(|e| {
93+
if e.is_cancelled() {
94+
SpawnBlockingError::Cancelled
95+
} else {
96+
SpawnBlockingError::Panic(e.into_panic())
97+
}
98+
}),
9599
#[cfg(feature = "async-std_1")]
96100
#[allow(deprecated)]
97101
Self::AsyncStd1 => Ok(async_std_1::task::spawn_blocking(f).await),
@@ -143,14 +147,40 @@ impl Runtime {
143147
pub enum SpawnBlockingError {
144148
/// Spawned task has panicked.
145149
Panic(Box<dyn Any + Send + 'static>),
150+
151+
/// Spawned task has been cancelled.
152+
Cancelled,
146153
}
147154

148155
impl fmt::Display for SpawnBlockingError {
149156
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150157
match self {
151158
Self::Panic(p) => write!(f, "SpawnBlockingError: Panic: {:?}", p),
159+
Self::Cancelled => write!(f, "SpawnBlockingError: Cancelled"),
152160
}
153161
}
154162
}
155163

156164
impl std::error::Error for SpawnBlockingError {}
165+
166+
#[cfg(all(test, feature = "tokio_1"))]
167+
mod tests_with_tokio_1 {
168+
use super::{Runtime, SpawnBlockingError};
169+
170+
#[tokio_1::test(crate = "tokio_1")]
171+
async fn test_spawning_blocking() {
172+
assert!(Runtime::Tokio1.spawn_blocking(|| 42).await.is_ok());
173+
}
174+
175+
#[tokio_1::test(crate = "tokio_1")]
176+
async fn test_spawning_blocking_can_panic() {
177+
assert!(matches!(
178+
Runtime::Tokio1
179+
.spawn_blocking(|| {
180+
panic!("42");
181+
})
182+
.await,
183+
Err(SpawnBlockingError::Panic(_))
184+
));
185+
}
186+
}

crates/deadpool-sync/src/lib.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ impl fmt::Display for InteractError {
5454

5555
impl std::error::Error for InteractError {}
5656

57+
impl From<SpawnBlockingError> for InteractError {
58+
fn from(value: SpawnBlockingError) -> Self {
59+
match value {
60+
SpawnBlockingError::Panic(p) => Self::Panic(p),
61+
SpawnBlockingError::Cancelled => Self::Aborted,
62+
}
63+
}
64+
}
65+
5766
/// Wrapper for objects which only provides blocking functions that need to be
5867
/// called on a separate thread.
5968
///
@@ -97,6 +106,7 @@ where
97106
// methods needs to support a custom error enum which
98107
// supports a Panic variant.
99108
Err(SpawnBlockingError::Panic(e)) => panic!("{e:?}"),
109+
Err(SpawnBlockingError::Cancelled) => panic!("Task has been cancelled"),
100110
Ok(obj) => obj,
101111
};
102112
result.map(|obj| Self {
@@ -127,7 +137,7 @@ where
127137
Ok(f(conn))
128138
})
129139
.await
130-
.map_err(|SpawnBlockingError::Panic(p)| InteractError::Panic(p))?
140+
.map_err(InteractError::from)?
131141
}
132142

133143
/// Indicates whether the underlying [`Mutex`] has been poisoned.

0 commit comments

Comments
 (0)