From 60508bd753e5a5bbf38f732196a30e93edb99fa6 Mon Sep 17 00:00:00 2001 From: Rain Date: Thu, 24 Aug 2023 17:05:09 -0700 Subject: [PATCH 1/2] sync: improve cancel-safety documentation for mpsc::Sender::send This specific issue (data loss because a send got cancelled) has bitten our team a couple of times over the last few months. We've switched to recommending this kind of reserve pattern instead. --- tokio/src/sync/mpsc/bounded.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tokio/src/sync/mpsc/bounded.rs b/tokio/src/sync/mpsc/bounded.rs index e870ae5f42e..1d58f89e8f8 100644 --- a/tokio/src/sync/mpsc/bounded.rs +++ b/tokio/src/sync/mpsc/bounded.rs @@ -439,7 +439,11 @@ impl Sender { /// /// If `send` is used as the event in a [`tokio::select!`](crate::select) /// statement and some other branch completes first, then it is guaranteed - /// that the message was not sent. + /// that the message was not sent. **However, in that case the message + /// is dropped and will be lost.** + /// + /// To avoid losing messages, use [`reserve`](Self::reserve) to reserve + /// capacity, then use the returned [`Permit`] to send the message. /// /// This channel uses a queue to ensure that calls to `send` and `reserve` /// complete in the order they were requested. Cancelling a call to From 0b605d3fbb3b2c20cdc5f584fb6f5e6e3a0ad682 Mon Sep 17 00:00:00 2001 From: Rain Date: Thu, 24 Aug 2023 17:18:28 -0700 Subject: [PATCH 2/2] address review nit --- tokio/src/sync/mpsc/bounded.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokio/src/sync/mpsc/bounded.rs b/tokio/src/sync/mpsc/bounded.rs index 1d58f89e8f8..8924dc22292 100644 --- a/tokio/src/sync/mpsc/bounded.rs +++ b/tokio/src/sync/mpsc/bounded.rs @@ -439,7 +439,7 @@ impl Sender { /// /// If `send` is used as the event in a [`tokio::select!`](crate::select) /// statement and some other branch completes first, then it is guaranteed - /// that the message was not sent. **However, in that case the message + /// that the message was not sent. **However, in that case, the message /// is dropped and will be lost.** /// /// To avoid losing messages, use [`reserve`](Self::reserve) to reserve