diff --git a/tokio/src/runtime/task/abort.rs b/tokio/src/runtime/task/abort.rs index 410f0a467..2745b5602 100644 --- a/tokio/src/runtime/task/abort.rs +++ b/tokio/src/runtime/task/abort.rs @@ -11,7 +11,14 @@ use std::panic::{RefUnwindSafe, UnwindSafe}; /// Dropping an `AbortHandle` releases the permission to terminate the task /// --- it does *not* abort the task. /// +/// Be aware that tasks spawned using [`spawn_blocking`] cannot be aborted +/// because they are not async. If you call `abort` on a `spawn_blocking` task, +/// then this *will not have any effect*, and the task will continue running +/// normally. The exception is if the task has not started running yet; in that +/// case, calling `abort` may prevent the task from starting. +/// /// [`JoinHandle`]: crate::task::JoinHandle +/// [`spawn_blocking`]: crate::task::spawn_blocking #[cfg_attr(docsrs, doc(cfg(feature = "rt")))] pub struct AbortHandle { raw: RawTask, @@ -31,11 +38,18 @@ impl AbortHandle { /// If the task was already cancelled, such as by [`JoinHandle::abort`], /// this method will do nothing. /// + /// Be aware that tasks spawned using [`spawn_blocking`] cannot be aborted + /// because they are not async. If you call `abort` on a `spawn_blocking` + /// task, then this *will not have any effect*, and the task will continue + /// running normally. The exception is if the task has not started running + /// yet; in that case, calling `abort` may prevent the task from starting. + /// /// See also [the module level docs] for more information on cancellation. /// /// [cancelled]: method@super::error::JoinError::is_cancelled /// [`JoinHandle::abort`]: method@super::JoinHandle::abort /// [the module level docs]: crate::task#cancellation + /// [`spawn_blocking`]: crate::task::spawn_blocking pub fn abort(&self) { self.raw.remote_abort(); } diff --git a/tokio/src/runtime/task/join.rs b/tokio/src/runtime/task/join.rs index 19289cf58..e646f6575 100644 --- a/tokio/src/runtime/task/join.rs +++ b/tokio/src/runtime/task/join.rs @@ -179,6 +179,12 @@ impl JoinHandle { /// already completed at the time it was cancelled, but most likely it /// will fail with a [cancelled] `JoinError`. /// + /// Be aware that tasks spawned using [`spawn_blocking`] cannot be aborted + /// because they are not async. If you call `abort` on a `spawn_blocking` + /// task, then this *will not have any effect*, and the task will continue + /// running normally. The exception is if the task has not started running + /// yet; in that case, calling `abort` may prevent the task from starting. + /// /// See also [the module level docs] for more information on cancellation. /// /// ```rust @@ -210,6 +216,7 @@ impl JoinHandle { /// /// [cancelled]: method@super::error::JoinError::is_cancelled /// [the module level docs]: crate::task#cancellation + /// [`spawn_blocking`]: crate::task::spawn_blocking pub fn abort(&self) { self.raw.remote_abort(); } diff --git a/tokio/src/task/blocking.rs b/tokio/src/task/blocking.rs index 1cce46639..193c28dfd 100644 --- a/tokio/src/task/blocking.rs +++ b/tokio/src/task/blocking.rs @@ -103,14 +103,11 @@ 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 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. + /// Be aware that tasks spawned using `spawn_blocking` cannot be aborted + /// because they are not async. If you call [`abort`] on a `spawn_blocking` + /// task, then this *will not have any effect*, and the task will continue + /// running normally. The exception is if the task has not started running + /// yet; in that case, calling `abort` may prevent the task from starting. /// /// 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 @@ -152,6 +149,7 @@ cfg_rt! { /// [`shutdown_timeout`]: fn@crate::runtime::Runtime::shutdown_timeout /// [bridgesync]: https://tokio.rs/tokio/topics/bridging /// [`AtomicBool`]: struct@std::sync::atomic::AtomicBool + /// [`abort`]: crate::task::JoinHandle::abort /// /// # Examples /// diff --git a/tokio/src/task/mod.rs b/tokio/src/task/mod.rs index 32a87c93c..0678aa3af 100644 --- a/tokio/src/task/mod.rs +++ b/tokio/src/task/mod.rs @@ -133,6 +133,12 @@ //! end of the task, then the [`JoinHandle`] will instead report that the task //! exited normally. //! +//! Be aware that tasks spawned using [`spawn_blocking`] cannot be aborted +//! because they are not async. If you call `abort` on a `spawn_blocking` +//! task, then this *will not have any effect*, and the task will continue +//! running normally. The exception is if the task has not started running +//! yet; in that case, calling `abort` may prevent the task from starting. +//! //! Be aware that calls to [`JoinHandle::abort`] just schedule the task for //! cancellation, and will return before the cancellation has completed. To wait //! for cancellation to complete, wait for the task to finish by awaiting the