Skip to content

Commit a0bb123

Browse files
committed
Replace wait_with_pipe() with wait_with_borrowed_pipe()
1 parent 548288f commit a0bb123

File tree

2 files changed

+3
-98
lines changed

2 files changed

+3
-98
lines changed

src/child.rs

Lines changed: 1 addition & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -117,49 +117,12 @@ impl FunChildren {
117117
}
118118
}
119119

120-
/// Pipes stdout from the last child in the pipeline to the given function, which runs in
121-
/// the current thread, then waits for all of the children to exit.
122-
///
123-
/// <div class=warning>
124-
///
125-
/// # Bugs
126-
///
127-
/// The exit status of the last child is **ignored**. If the function returns early, without
128-
/// reading from stdout until the last child exits, then the last child may be killed instead
129-
/// of being waited for. To avoid these limitations, use [`Self::wait_with_stdout_thread`].
130-
/// </div>
131-
pub fn wait_with_pipe(&mut self, f: &mut dyn FnMut(Box<dyn Read>)) -> CmdResult {
132-
let child = self.children.pop().unwrap();
133-
let stderr_thread =
134-
StderrThread::new(&child.cmd, &child.file, child.line, child.stderr, false);
135-
match child.handle {
136-
CmdChildHandle::Proc(mut proc) => {
137-
if let Some(stdout) = child.stdout {
138-
f(Box::new(stdout));
139-
let _ = proc.kill();
140-
}
141-
}
142-
CmdChildHandle::Thread(_) => {
143-
if let Some(stdout) = child.stdout {
144-
f(Box::new(stdout));
145-
}
146-
}
147-
CmdChildHandle::SyncFn => {
148-
if let Some(stdout) = child.stdout {
149-
f(Box::new(stdout));
150-
}
151-
}
152-
};
153-
drop(stderr_thread);
154-
CmdChildren::wait_children(&mut self.children)
155-
}
156-
157120
/// Pipes stdout from the last child in the pipeline to the given function, which runs in
158121
/// the current thread, then waits for all of the children to exit.
159122
///
160123
/// If the function returns early, without reading from stdout until the last child exits,
161124
/// then the rest of stdout is automatically read and discarded to allow the child to finish.
162-
pub fn wait_with_borrowed_pipe(&mut self, f: &mut dyn FnMut(&mut Box<dyn Read>)) -> CmdResult {
125+
pub fn wait_with_pipe(&mut self, f: &mut dyn FnMut(&mut Box<dyn Read>)) -> CmdResult {
163126
let mut last_child = self.children.pop().unwrap();
164127
let mut stderr_thread = StderrThread::new(
165128
&last_child.cmd,

tests/test_macros.rs

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ fn test_tls_set() {
134134
}
135135

136136
#[test]
137-
fn test_pipe() -> CmdResult {
137+
fn test_pipe() {
138138
assert!(run_cmd!(echo "xx").is_ok());
139139
assert_eq!(run_fun!(echo "xx").unwrap(), "xx");
140140
assert!(run_cmd!(echo xx | wc).is_ok());
@@ -246,7 +246,7 @@ fn test_pipe() -> CmdResult {
246246
.wait_with_raw_output(&mut vec![])),
247247
test_cases_for_entry_point!((spawn_with_output!(...))
248248
.unwrap()
249-
.wait_with_borrowed_pipe(&mut |_stdout| {})),
249+
.wait_with_pipe(&mut |_stdout| {})),
250250
];
251251

252252
macro_rules! check_eq {
@@ -281,64 +281,6 @@ fn test_pipe() -> CmdResult {
281281
}
282282

283283
assert!(ok);
284-
285-
// test that illustrates the bugs in wait_with_pipe()
286-
// FIXME: make set_pipefail() thread safe, then move this to a separate test function
287-
assert!(spawn_with_output!(false)?.wait_with_all().0.is_err());
288-
assert!(spawn_with_output!(false)?.wait_with_output().is_err());
289-
assert!(spawn_with_output!(false)?
290-
.wait_with_raw_output(&mut vec![])
291-
.is_err());
292-
293-
// wait_with_pipe() can’t check the exit status of the last child
294-
assert!(spawn_with_output!(false)?
295-
.wait_with_pipe(&mut |_stdout| {})
296-
.is_ok());
297-
298-
// wait_with_pipe() kills the last child when the provided function returns
299-
assert!(spawn_with_output!(sh -c "while :; do :; done")?
300-
.wait_with_pipe(&mut |_stdout| {})
301-
.is_ok());
302-
303-
// wait_with_borrowed_pipe() checks the exit status of the last child, even if pipefail is disabled
304-
set_pipefail(false);
305-
assert!(spawn_with_output!(true | false)?
306-
.wait_with_borrowed_pipe(&mut |_stdout| {})
307-
.is_err());
308-
assert!(spawn_with_output!(true | true)?
309-
.wait_with_borrowed_pipe(&mut |_stdout| {})
310-
.is_ok());
311-
assert!(spawn_with_output!(false)?
312-
.wait_with_borrowed_pipe(&mut |_stdout| {})
313-
.is_err());
314-
assert!(spawn_with_output!(true)?
315-
.wait_with_borrowed_pipe(&mut |_stdout| {})
316-
.is_ok());
317-
set_pipefail(true);
318-
// wait_with_borrowed_pipe() checks the exit status of the other children, unless pipefail is disabled
319-
set_pipefail(false);
320-
assert!(spawn_with_output!(false | true)?
321-
.wait_with_borrowed_pipe(&mut |_stdout| {})
322-
.is_ok());
323-
set_pipefail(true);
324-
assert!(spawn_with_output!(false | true)?
325-
.wait_with_borrowed_pipe(&mut |_stdout| {})
326-
.is_err());
327-
assert!(spawn_with_output!(true | true)?
328-
.wait_with_borrowed_pipe(&mut |_stdout| {})
329-
.is_ok());
330-
// wait_with_borrowed_pipe() handles `ignore`
331-
assert!(spawn_with_output!(ignore false | true)?
332-
.wait_with_borrowed_pipe(&mut |_stdout| {})
333-
.is_ok());
334-
assert!(spawn_with_output!(ignore true | false)?
335-
.wait_with_borrowed_pipe(&mut |_stdout| {})
336-
.is_ok());
337-
assert!(spawn_with_output!(ignore false)?
338-
.wait_with_borrowed_pipe(&mut |_stdout| {})
339-
.is_ok());
340-
341-
Ok(())
342284
}
343285

344286
#[test]

0 commit comments

Comments
 (0)