|
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