Skip to content

Commit

Permalink
task: clarify that you can't abort spawn_blocking tasks (#6571)
Browse files Browse the repository at this point in the history
  • Loading branch information
Darksonn committed May 19, 2024
1 parent daa8901 commit a024071
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 8 deletions.
14 changes: 14 additions & 0 deletions tokio/src/runtime/task/abort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();
}
Expand Down
7 changes: 7 additions & 0 deletions tokio/src/runtime/task/join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ impl<T> JoinHandle<T> {
/// 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
Expand Down Expand Up @@ -210,6 +216,7 @@ impl<T> JoinHandle<T> {
///
/// [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();
}
Expand Down
14 changes: 6 additions & 8 deletions tokio/src/task/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
///
Expand Down
6 changes: 6 additions & 0 deletions tokio/src/task/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a024071

Please sign in to comment.