task: clarify what happens to spawned work during runtime shutdown (#5394)

This commit is contained in:
Valentin 2023-02-09 11:14:01 +01:00 committed by GitHub
parent d7d5d05333
commit 061325ba7e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 23 deletions

View File

@ -156,9 +156,11 @@
//! multi-thread scheduler spawns threads to schedule tasks and for `spawn_blocking` //! multi-thread scheduler spawns threads to schedule tasks and for `spawn_blocking`
//! calls. //! calls.
//! //!
//! While the `Runtime` is active, threads may shutdown after periods of being //! While the `Runtime` is active, threads may shut down after periods of being
//! idle. Once `Runtime` is dropped, all runtime threads are forcibly shutdown. //! idle. Once `Runtime` is dropped, all runtime threads have usually been
//! Any tasks that have not yet completed will be dropped. //! terminated, but in the presence of unstoppable spawned work are not
//! guaranteed to have been terminated. See the
//! [struct level documentation](Runtime#shutdown) for more details.
//! //!
//! [tasks]: crate::task //! [tasks]: crate::task
//! [`Runtime`]: Runtime //! [`Runtime`]: Runtime

View File

@ -24,16 +24,29 @@ cfg_rt_multi_thread! {
/// ///
/// # Shutdown /// # Shutdown
/// ///
/// Shutting down the runtime is done by dropping the value. The current /// Shutting down the runtime is done by dropping the value, or calling
/// thread will block until the shut down operation has completed. /// [`Runtime::shutdown_background`] or [`Runtime::shutdown_timeout`].
/// ///
/// * Drain any scheduled work queues. /// Tasks spawned through [`Runtime::spawn`] keep running until they yield.
/// * Drop any futures that have not yet completed. /// Then they are dropped. They are not *guaranteed* to run to completion, but
/// * Drop the reactor. /// *might* do so if they do not yield until completion.
/// ///
/// Once the reactor has dropped, any outstanding I/O resources bound to /// Blocking functions spawned through [`Runtime::spawn_blocking`] keep running
/// that reactor will no longer function. Calling any method on them will /// until they return.
/// result in an error. ///
/// The thread initiating the shutdown blocks until all spawned work has been
/// stopped. This can take an indefinite amount of time. The `Drop`
/// implementation waits forever for this.
///
/// `shutdown_background` and `shutdown_timeout` can be used if waiting forever
/// is undesired. When the timeout is reached, spawned work that did not stop
/// in time and threads running it are leaked. The work continues to run until
/// one of the stopping conditions is fulfilled, but the thread initiating the
/// shutdown is unblocked.
///
/// Once the runtime has been dropped, any outstanding I/O resources bound to
/// it will no longer function. Calling any method on them will result in an
/// error.
/// ///
/// # Sharing /// # Sharing
/// ///
@ -322,18 +335,9 @@ impl Runtime {
} }
/// Shuts down the runtime, waiting for at most `duration` for all spawned /// Shuts down the runtime, waiting for at most `duration` for all spawned
/// task to shutdown. /// work to stop.
/// ///
/// Usually, dropping a `Runtime` handle is sufficient as tasks are able to /// See the [struct level documentation](Runtime#shutdown) for more details.
/// shutdown in a timely fashion. However, dropping a `Runtime` will wait
/// indefinitely for all tasks to terminate, and there are cases where a long
/// blocking task has been spawned, which can block dropping `Runtime`.
///
/// In this case, calling `shutdown_timeout` with an explicit wait timeout
/// can work. The `shutdown_timeout` will signal all tasks to shutdown and
/// will wait for at most `duration` for all spawned tasks to terminate. If
/// `timeout` elapses before all tasks are dropped, the function returns and
/// outstanding tasks are potentially leaked.
/// ///
/// # Examples /// # Examples
/// ///
@ -362,7 +366,7 @@ impl Runtime {
self.blocking_pool.shutdown(Some(duration)); self.blocking_pool.shutdown(Some(duration));
} }
/// Shuts down the runtime, without waiting for any spawned tasks to shutdown. /// Shuts down the runtime, without waiting for any spawned work to stop.
/// ///
/// This can be useful if you want to drop a runtime from within another runtime. /// This can be useful if you want to drop a runtime from within another runtime.
/// Normally, dropping a runtime will block indefinitely for spawned blocking tasks /// Normally, dropping a runtime will block indefinitely for spawned blocking tasks
@ -373,6 +377,8 @@ impl Runtime {
/// may result in a resource leak (in that any blocking tasks are still running until they /// may result in a resource leak (in that any blocking tasks are still running until they
/// return. /// return.
/// ///
/// See the [struct level documentation](Runtime#shutdown) for more details.
///
/// This function is equivalent to calling `shutdown_timeout(Duration::from_nanos(0))`. /// This function is equivalent to calling `shutdown_timeout(Duration::from_nanos(0))`.
/// ///
/// ``` /// ```