|
71 | 71 | //! .spawn()
|
72 | 72 | //! .expect("failed to execute child");
|
73 | 73 | //!
|
74 |
| -//! { |
75 |
| -//! // limited borrow of stdin |
76 |
| -//! let stdin = child.stdin.as_mut().expect("failed to get stdin"); |
| 74 | +//! // If the child process fills its stdout buffer, it may end up |
| 75 | +//! // waiting until the parent reads the stdout, and not be able to |
| 76 | +//! // read stdin in the meantime, causing a deadlock. |
| 77 | +//! // Writing from another thread ensures that stdout is being read |
| 78 | +//! // at the same time, avoiding the problem. |
| 79 | +//! let mut stdin = child.stdin.take().expect("failed to get stdin"); |
| 80 | +//! std::thread::spawn(move || { |
77 | 81 | //! stdin.write_all(b"test").expect("failed to write to stdin");
|
78 |
| -//! } |
| 82 | +//! }); |
79 | 83 | //!
|
80 | 84 | //! let output = child
|
81 | 85 | //! .wait_with_output()
|
@@ -1145,14 +1149,21 @@ impl Stdio {
|
1145 | 1149 | /// .spawn()
|
1146 | 1150 | /// .expect("Failed to spawn child process");
|
1147 | 1151 | ///
|
1148 |
| - /// { |
1149 |
| - /// let stdin = child.stdin.as_mut().expect("Failed to open stdin"); |
| 1152 | + /// let mut stdin = child.stdin.take().expect("Failed to open stdin"); |
| 1153 | + /// std::thread::spawn(move || { |
1150 | 1154 | /// stdin.write_all("Hello, world!".as_bytes()).expect("Failed to write to stdin");
|
1151 |
| - /// } |
| 1155 | + /// }); |
1152 | 1156 | ///
|
1153 | 1157 | /// let output = child.wait_with_output().expect("Failed to read stdout");
|
1154 | 1158 | /// assert_eq!(String::from_utf8_lossy(&output.stdout), "!dlrow ,olleH");
|
1155 | 1159 | /// ```
|
| 1160 | + /// |
| 1161 | + /// Writing more than a pipe buffer's worth of input to stdin without also reading |
| 1162 | + /// stdout and stderr at the same time may cause a deadlock. |
| 1163 | + /// This is an issue when running any program that doesn't guarantee that it reads |
| 1164 | + /// its entire stdin before writing more than a pipe buffer's worth of output. |
| 1165 | + /// The size of a pipe buffer varies on different targets. |
| 1166 | + /// |
1156 | 1167 | #[stable(feature = "process", since = "1.0.0")]
|
1157 | 1168 | pub fn piped() -> Stdio {
|
1158 | 1169 | Stdio(imp::Stdio::MakePipe)
|
|
0 commit comments