You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2024/06/04 02:45:59 UTC
(opendal) 01/01: fix(core): RetryLayer could panic when other threads raises panic
This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch fix-retry-panic
in repository https://gitbox.apache.org/repos/asf/opendal.git
commit 91e8e57e0969d2a9bd7d689cd5b4559bb7e238a1
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Tue Jun 4 10:45:17 2024 +0800
fix(core): RetryLayer could panic when other threads raises panic
Signed-off-by: Xuanwo <gi...@xuanwo.io>
---
core/src/layers/retry.rs | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/core/src/layers/retry.rs b/core/src/layers/retry.rs
index 71b7195c07..44df4fa1d4 100644
--- a/core/src/layers/retry.rs
+++ b/core/src/layers/retry.rs
@@ -546,13 +546,23 @@ impl<R, I> RetryWrapper<R, I> {
builder: backoff,
}
}
+
+ /// We can't make sure inner is valid in cases like panic, so we need to return an error instead.
+ fn take_inner(&mut self) -> Result<R> {
+ self.inner.take().ok_or_else(|| {
+ Error::new(
+ ErrorKind::Unexpected,
+ "retry wrapper inner must be valid but not, maybe panic happened",
+ )
+ })
+ }
}
impl<R: oio::Read, I: RetryInterceptor> oio::Read for RetryWrapper<R, I> {
async fn read(&mut self) -> Result<Buffer> {
use backon::RetryableWithContext;
- let inner = self.inner.take().expect("inner must be valid");
+ let inner = self.take_inner()?;
let (inner, res) = {
|mut r: R| async move {
@@ -576,7 +586,7 @@ impl<R: oio::BlockingRead, I: RetryInterceptor> oio::BlockingRead for RetryWrapp
fn read(&mut self) -> Result<Buffer> {
use backon::BlockingRetryableWithContext;
- let inner = self.inner.take().expect("inner must be valid");
+ let inner = self.take_inner()?;
let (inner, res) = {
|mut r: R| {
@@ -600,7 +610,7 @@ impl<R: oio::Write, I: RetryInterceptor> oio::Write for RetryWrapper<R, I> {
async fn write(&mut self, bs: Buffer) -> Result<usize> {
use backon::RetryableWithContext;
- let inner = self.inner.take().expect("inner must be valid");
+ let inner = self.take_inner()?;
let ((inner, _), res) = {
|(mut r, bs): (R, Buffer)| async move {
@@ -622,7 +632,7 @@ impl<R: oio::Write, I: RetryInterceptor> oio::Write for RetryWrapper<R, I> {
async fn abort(&mut self) -> Result<()> {
use backon::RetryableWithContext;
- let inner = self.inner.take().expect("inner must be valid");
+ let inner = self.take_inner()?;
let (inner, res) = {
|mut r: R| async move {
@@ -644,7 +654,7 @@ impl<R: oio::Write, I: RetryInterceptor> oio::Write for RetryWrapper<R, I> {
async fn close(&mut self) -> Result<()> {
use backon::RetryableWithContext;
- let inner = self.inner.take().expect("inner must be valid");
+ let inner = self.take_inner()?;
let (inner, res) = {
|mut r: R| async move {
@@ -692,7 +702,7 @@ impl<P: oio::List, I: RetryInterceptor> oio::List for RetryWrapper<P, I> {
async fn next(&mut self) -> Result<Option<oio::Entry>> {
use backon::RetryableWithContext;
- let inner = self.inner.take().expect("inner must be valid");
+ let inner = self.take_inner()?;
let (inner, res) = {
|mut p: P| async move {