bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] make should not turn the append mode on its stdout


From: 0xef967c36
Subject: [PATCH] make should not turn the append mode on its stdout
Date: Sun, 2 Feb 2020 08:24:45 +0200

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;



reply via email to

[Prev in Thread] Current Thread [Next in Thread]