From 8e20cfb9efe41bbda85c2814c20a5bfd1070bce9 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 13 Jul 2022 10:41:13 -0400 Subject: [PATCH] task: expand on cancellation of `spawn_blocking` (#4811) I was looking at these docs again and I was thinking the "cannot be cancelled" is misleading; let's talk about approaches to do so. --- tokio/src/task/blocking.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/tokio/src/task/blocking.rs b/tokio/src/task/blocking.rs index 5fe358f3e50..a817f83d5e5 100644 --- a/tokio/src/task/blocking.rs +++ b/tokio/src/task/blocking.rs @@ -102,11 +102,21 @@ cfg_rt! { /// their own. If you want to spawn an ordinary thread, you should use /// [`thread::spawn`] instead. /// - /// Closures spawned using `spawn_blocking` cannot be cancelled. When you shut - /// down the executor, it will wait indefinitely for all blocking operations to + /// Closures spawned using `spawn_blocking` cannot be cancelled abruptly; there + /// is no standard low level API to cause a thread to stop running. However, + /// a useful pattern is to pass some form of "cancellation token" into + /// the thread. This could be an [`AtomicBool`] that the task checks periodically. + /// Another approach is to have the thread primarily read or write from a channel, + /// and to exit when the channel closes; assuming the other side of the channel is dropped + /// when cancellation occurs, this will cause the blocking task thread to exit + /// soon after as well. + /// + /// When you shut down the executor, it will wait indefinitely for all blocking operations to /// finish. You can use [`shutdown_timeout`] to stop waiting for them after a /// certain timeout. Be aware that this will still not cancel the tasks — they - /// are simply allowed to keep running after the method returns. + /// are simply allowed to keep running after the method returns. It is possible + /// for a blocking task to be cancelled if it has not yet started running, but this + /// is not guaranteed. /// /// Note that if you are using the single threaded runtime, this function will /// still spawn additional threads for blocking operations. The basic @@ -140,6 +150,7 @@ cfg_rt! { /// [`thread::spawn`]: fn@std::thread::spawn /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout /// [bridgesync]: https://tokio.rs/tokio/topics/bridging + /// [`AtomicBool`]: struct@std::sync::atomic::AtomicBool /// /// # Examples ///