summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Petkov <ivanppetkov@gmail.com>2020-10-12 17:42:17 -0700
committerGitHub <noreply@github.com>2020-10-13 00:42:17 +0000
commita249421abc44e768217427a68f5f5e23f9d1cbd5 (patch)
tree66cf828092c0a983ce335aa7da43566077e1e22c
parent19233508806ddf22a14acf944426e0da8a401df8 (diff)
process: update docs regarding zombie processes (#2952)
-rw-r--r--tokio/src/process/mod.rs100
1 files changed, 90 insertions, 10 deletions
diff --git a/tokio/src/process/mod.rs b/tokio/src/process/mod.rs
index ff84428e..ad64371a 100644
--- a/tokio/src/process/mod.rs
+++ b/tokio/src/process/mod.rs
@@ -99,6 +99,8 @@
//!
//! # Caveats
//!
+//! ## Dropping/Cancellation
+//!
//! Similar to the behavior to the standard library, and unlike the futures
//! paradigm of dropping-implies-cancellation, a spawned process will, by
//! default, continue to execute even after the `Child` handle has been dropped.
@@ -107,7 +109,25 @@
//! and kill the child process if the `Child` wrapper is dropped before it
//! has exited.
//!
+//! ## Unix Processes
+//!
+//! On Unix platforms processes must be "reaped" by their parent process after
+//! they have exited in order to release all OS resources. A child process which
+//! has exited, but has not yet been reaped by its parent is considered a "zombie"
+//! process. Such processes continue to count against limits imposed by the system,
+//! and having too many zombie processes present can prevent additional processes
+//! from being spawned.
+//!
+//! The tokio runtime will, on a best-effort basis, attempt to reap and clean up
+//! any process which it has spawned. No additional guarantees are made with regards
+//! how quickly or how often this procedure will take place.
+//!
+//! It is recommended to avoid dropping a [`Child`] process handle before it has been
+//! fully `await`ed if stricter cleanup guarantees are required.
+//!
//! [`Command`]: crate::process::Command
+//! [`Command::kill_on_drop`]: crate::process::Command::kill_on_drop
+//! [`Child`]: crate::process::Child
#[path = "unix/mod.rs"]
#[cfg(unix)]
@@ -454,6 +474,26 @@ impl Command {
/// By default, this value is assumed to be `false`, meaning the next spawned
/// process will not be killed on drop, similar to the behavior of the standard
/// library.
+ ///
+ /// # Caveats
+ ///
+ /// On Unix platforms processes must be "reaped" by their parent process after
+ /// they have exited in order to release all OS resources. A child process which
+ /// has exited, but has not yet been reaped by its parent is considered a "zombie"
+ /// process. Such processes continue to count against limits imposed by the system,
+ /// and having too many zombie processes present can prevent additional processes
+ /// from being spawned.
+ ///
+ /// Although issuing a `kill` signal to the child process is a synchronous
+ /// operation, the resulting zombie process cannot be `.await`ed inside of the
+ /// destructor to avoid blocking other tasks. The tokio runtime will, on a
+ /// best-effort basis, attempt to reap and clean up such processes in the
+ /// background, but makes no additional guarantees are made with regards
+ /// how quickly or how often this procedure will take place.
+ ///
+ /// If stronger guarantees are required, it is recommended to avoid dropping
+ /// a [`Child`] handle where possible, and instead utilize `child.wait().await`
+ /// or `child.kill().await` where possible.
pub fn kill_on_drop(&mut self, kill_on_drop: bool) -> &mut Command {
self.kill_on_drop = kill_on_drop;
self
@@ -538,16 +578,6 @@ impl Command {
/// All I/O this child does will be associated with the current default
/// event loop.
///
- /// # Caveats
- ///
- /// Similar to the behavior to the standard library, and unlike the futures
- /// paradigm of dropping-implies-cancellation, the spawned process will, by
- /// default, continue to execute even after the `Child` handle has been dropped.
- ///
- /// The `Command::kill_on_drop` method can be used to modify this behavior
- /// and kill the child process if the `Child` wrapper is dropped before it
- /// has exited.
- ///
/// # Examples
///
/// Basic usage:
@@ -564,6 +594,44 @@ impl Command {
/// .expect("ls command failed to run")
/// }
/// ```
+ ///
+ /// # Caveats
+ ///
+ /// ## Dropping/Cancellation
+ ///
+ /// Similar to the behavior to the standard library, and unlike the futures
+ /// paradigm of dropping-implies-cancellation, a spawned process will, by
+ /// default, continue to execute even after the `Child` handle has been dropped.
+ ///
+ /// The [`Command::kill_on_drop`] method can be used to modify this behavior
+ /// and kill the child process if the `Child` wrapper is dropped before it
+ /// has exited.
+ ///
+ /// ## Unix Processes
+ ///
+ /// On Unix platforms processes must be "reaped" by their parent process after
+ /// they have exited in order to release all OS resources. A child process which
+ /// has exited, but has not yet been reaped by its parent is considered a "zombie"
+ /// process. Such processes continue to count against limits imposed by the system,
+ /// and having too many zombie processes present can prevent additional processes
+ /// from being spawned.
+ ///
+ /// The tokio runtime will, on a best-effort basis, attempt to reap and clean up
+ /// any process which it has spawned. No additional guarantees are made with regards
+ /// how quickly or how often this procedure will take place.
+ ///
+ /// It is recommended to avoid dropping a [`Child`] process handle before it has been
+ /// fully `await`ed if stricter cleanup guarantees are required.
+ ///
+ /// [`Command`]: crate::process::Command
+ /// [`Command::kill_on_drop`]: crate::process::Command::kill_on_drop
+ /// [`Child`]: crate::process::Child
+ ///
+ /// # Errors
+ ///
+ /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
+ /// if the system process limit is reached (which includes other applications
+ /// running on the system).
pub fn spawn(&mut self) -> io::Result<Child> {
imp::spawn_child(&mut self.std).map(|spawned_child| Child {
child: FusedChild::Child(ChildDropGuard {
@@ -596,6 +664,10 @@ impl Command {
/// This future will return an error if the child process cannot be spawned
/// or if there is an error while awaiting its status.
///
+ /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
+ /// if the system process limit is reached (which includes other applications
+ /// running on the system).
+ ///
/// # Examples
///
/// Basic usage:
@@ -650,6 +722,14 @@ impl Command {
///
/// [`kill_on_drop`]: fn@Self::kill_on_drop
///
+ /// # Errors
+ ///
+ /// This future will return an error if the child process cannot be spawned
+ /// or if there is an error while awaiting its status.
+ ///
+ /// On Unix platforms this method will fail with `std::io::ErrorKind::WouldBlock`
+ /// if the system process limit is reached (which includes other applications
+ /// running on the system).
/// # Examples
///
/// Basic usage: