Since O_APPEND is common to all the file descriptors referring to an open file, this breaks other processes which have an open handle to the same file.
On Linux, this behaviour of make cause a subsequent splice(2) or sendfile(2) on the same file to fail, /even/ if the file is a tty or a character device like /dev/null: --------------------->snip<----------------------- $ cat >scat.c <<'EOT' #define _GNU_SOURCE #include <fcntl.h> #include <err.h> int main(int ac, char **av){ int r; while((r = splice(0, 0, 1, 0, 4096, 0))) if(r < 0) err(1, "splice"); } EOT $ cc -Wall scat.c -o scat $ true | ./scat # OK the first time $ make 2>/dev/null $ true | ./scat scat: splice: Invalid argument # WHY? $ true | ./scat >/dev/null $ { make 2>/dev/null; true | ./scat; } >/dev/null scat: splice: Invalid argument --------------------->snip<----------------------- A real fix would be to get rid of this behavior (and maybe just warn if the output is a /seekable file/ /not/ in a append mode, so the user should know to run ">log; make -j13 >> log" instead). But in the meanwhile you could at least only set O_APPEND on /regular/ files, not on ttys/devices, pipes, sockets, etc: diff --git a/src/output.c b/src/output.c index 2211749..16c3456 100644 --- a/src/output.c +++ b/src/output.c @@ -144,14 +144,18 @@ log_working_directory (int entering) return 1; } -/* Set a file descriptor to be in O_APPEND mode. - If it fails, just ignore it. */ +/* Set a file descriptor referring to a regular file + to be in O_APPEND mode. If it fails, just ignore it. */ static void set_append_mode (int fd) { #if defined(F_GETFL) && defined(F_SETFL) && defined(O_APPEND) - int flags = fcntl (fd, F_GETFL, 0); + struct stat stbuf; + int flags; + if (fstat (fd, &stbuf) != 0 || !S_ISREG (stbuf.st_mode)) + return; + flags = fcntl (fd, F_GETFL, 0); if (flags >= 0) { int r;