The following Makefile illustrates the issue: $ cat >Makefile <<EOF all: echo "abc" | grep "b" .PHONY: all $ make all # works as expected $ make all > /dev/null grep: (standard input): Invalid argument make: *** [Makefile:2: all] Error 2
The bug was introduced by commit 4fa6f48b573267e758650e114ec158d97916411e (introducing the usage of splice), which was first released in grep version 2.27. My environment: $ make --version GNU Make 4.2.1 Built for x86_64-pc-linux-gnu Copyright (C) 1988-2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html > This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ grep --version grep (GNU grep) 2.27 Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html >. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Written by Mike Haertel and others, see < http://git.sv.gnu.org/cgit/grep.git/tree/AUTHORS>. Patch attached. -- Benno Fünfstück
diff --git a/src/grep.c b/src/grep.c index f28f3c2..3e8e662 100644 --- a/src/grep.c +++ b/src/grep.c @@ -1729,10 +1729,19 @@ drain_input (int fd, struct stat const *st) #ifdef SPLICE_F_MOVE /* Should be faster, since it need not copy data to user space. */ while ((nbytes = splice (fd, NULL, STDOUT_FILENO, NULL, - INITIAL_BUFSIZE, SPLICE_F_MOVE))) - if (nbytes < 0) - return false; - return true; + INITIAL_BUFSIZE, SPLICE_F_MOVE)) > 0) + continue; + + if(nbytes == 0) return true; + + /* STDOUT might have been opened with O_APPEND (gnumake sets this flag for example). + * In this case, splice fails with EINVAL. + * + * In that case, the safe_read still works so instead of returning with an error here, + * we just fall through to the safe_read variant. + */ + if(nbytes < 0 && errno != EINVAL) return false; + #endif } while ((nbytes = safe_read (fd, buffer, bufalloc)))