|
5 | 5 |
|
6 | 6 | // spell-checker:ignore (ToDO) nonprint nonblank nonprinting ELOOP |
7 | 7 | use std::fs::{metadata, File}; |
8 | | -use std::io::{self, IsTerminal, Read, Write}; |
| 8 | +use std::io::{self, BufWriter, IsTerminal, Read, Write}; |
9 | 9 | /// Unix domain socket support |
10 | 10 | #[cfg(unix)] |
11 | 11 | use std::net::Shutdown; |
@@ -511,9 +511,12 @@ fn write_lines<R: FdReadable>( |
511 | 511 | ) -> CatResult<()> { |
512 | 512 | let mut in_buf = [0; 1024 * 31]; |
513 | 513 | let stdout = io::stdout(); |
514 | | - let mut writer = stdout.lock(); |
| 514 | + let stdout = stdout.lock(); |
| 515 | + // Add a 32K buffer for stdout - this greatly improves performance. |
| 516 | + let mut writer = BufWriter::with_capacity(32 * 1024, stdout); |
515 | 517 |
|
516 | 518 | while let Ok(n) = handle.reader.read(&mut in_buf) { |
| 519 | + eprintln!("Read complete"); |
517 | 520 | if n == 0 { |
518 | 521 | break; |
519 | 522 | } |
@@ -560,6 +563,14 @@ fn write_lines<R: FdReadable>( |
560 | 563 | } |
561 | 564 | pos += offset + 1; |
562 | 565 | } |
| 566 | + // We need to flush the buffer each time around the loop in order to pass GNU tests. |
| 567 | + // When we are reading the input from a pipe, the `handle.reader.read` call at the top |
| 568 | + // of this loop will block (indefinitely) whist waiting for more data. The expectation |
| 569 | + // however is that anything that's ready for output should show up in the meantime, |
| 570 | + // and not be buffered internally to the `cat` process. |
| 571 | + // Hence it's necessary to flush our buffer before every time we could potentially block |
| 572 | + // on a `std::io::Read::read` call. |
| 573 | + writer.flush()?; |
563 | 574 | } |
564 | 575 |
|
565 | 576 | Ok(()) |
|
0 commit comments