When st_size is not usable, truncate opens the --reference operand and uses lseek(SEEK_END) to obtain a size. Opening a FIFO with O_RDONLY blocks until a writer appears, so "truncate --reference=fifo file" could hang indefinitely. Use O_NONBLOCK, matching the existing open of the output file and the approach taken in df.
Introduced by commit v8.16-49-g9d308df13. * NEWS: Mention the fix. * src/truncate.c (main): Open the reference with O_NONBLOCK. * tests/truncate/truncate-fifo.sh: Also cover --reference=FIFO. Signed-off-by: Iván Ezequiel Rodriguez <[email protected]> --- NEWS | 3 +++ src/truncate.c | 3 ++- tests/truncate/truncate-fifo.sh | 8 ++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 67ffc1bf2..946627523 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,9 @@ GNU coreutils NEWS -*- outline -*- with an error. [This bug was present in "the beginning".] + 'truncate --reference=R' no longer hangs when R is a FIFO. + [bug introduced in coreutils-8.17] + 'unexpand -t' no longer overflows a heap buffer, for tab values > SIZE_MAX/16, or with multi-byte blank characters longer than the tab value. [bugs introduced in coreutils-9.11] diff --git a/src/truncate.c b/src/truncate.c index 7119132e0..e6c20b70a 100644 --- a/src/truncate.c +++ b/src/truncate.c @@ -326,7 +326,8 @@ main (int argc, char **argv) file_size = sb.st_size; else { - int ref_fd = open (ref_file, O_RDONLY); + /* O_NONBLOCK so we do not hang forever on a FIFO with no writer. */ + int ref_fd = open (ref_file, O_RDONLY | O_NONBLOCK); if (0 <= ref_fd) { off_t file_end = lseek (ref_fd, 0, SEEK_END); diff --git a/tests/truncate/truncate-fifo.sh b/tests/truncate/truncate-fifo.sh index c456c76ff..9b8a40910 100755 --- a/tests/truncate/truncate-fifo.sh +++ b/tests/truncate/truncate-fifo.sh @@ -21,7 +21,15 @@ print_ver_ truncate mkfifo_or_skip_ fifo + +# Output FIFO must not hang. timeout 10 truncate -s0 fifo test "$?" = 124 && fail=1 +# Reference FIFO must not hang either. +touch file || framework_failure_ +timeout 10 truncate --reference=fifo file 2>/dev/null +test "$?" = 124 && fail=1 + + Exit $fail -- 2.43.0
