From 4f26b4c6ff9ec3f3dbc0c0269187539eb029ca14 Mon Sep 17 00:00:00 2001 From: Uwe Klotz Date: Thu, 21 Sep 2023 21:19:50 +0200 Subject: [PATCH] watch::Receiver::wait_for(): Prevent poisoning of the lock --- tokio/src/sync/watch.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/tokio/src/sync/watch.rs b/tokio/src/sync/watch.rs index fa1ad05139c..89ac6891cb4 100644 --- a/tokio/src/sync/watch.rs +++ b/tokio/src/sync/watch.rs @@ -772,8 +772,24 @@ impl Receiver { let has_changed = self.version != new_version; self.version = new_version; - if (!closed || has_changed) && f(&inner) { - return Ok(Ref { inner, has_changed }); + if !closed || has_changed { + let result = + panic::catch_unwind(panic::AssertUnwindSafe(|| f(&inner))); + match result { + Ok(true) => { + return Ok(Ref { inner, has_changed }); + } + Ok(false) => { + // Skip the value. + } + Err(panicked) => { + // Drop the read-lock to avoid poisoning it. + drop(inner); + // Forward the panic to the caller. + panic::resume_unwind(panicked); + // Unreachable + } + }; } }