Subject: Re: bug#47596: File descriptor error when exiting emacs on android 11

From: Henrik Grimler <[email-masked]>
Date: Tue, 11 May 2021 19:06:11 +0200

Hi again,

Enh at google suggested [1] that `setlinebuf (stderr)` could be an
alternative instead of opening a copy of stderr.  I tried out the
attached patch, which removes the buferr variable and uses setlinebuf
on stderr instead, and it seem to work (in the sense that emacs opens
and closes without errors) on archlinux as well as android. 

Could this work or do we need to have both buferr and stderr?

Best regards,
Henrik Grimler

[1] https://issuetracker.google.com/issues/184380442
commit ef3beaf664347f7fce1f3475fe65de729320837e
Author: Henrik Grimler <[email-masked]>
Date:   Tue May 11 09:36:52 2021 +0200

    Use setlinebuf to make stderr line buffered
    
    If atomic writes are supported.  Android >= 10 has a file descriptor
    sanitizer which errors if a stream is closed while there are still
    fd's associated with it. In emacs stderr is opened twice if line
    buffered streams are supported.  Rather than opening a copy we can
    make stderr line buffered with setlinebuf instead.

diff --git a/src/sysdep.c b/src/sysdep.c
index d940acc4e0..77e1a0be3c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -232,10 +232,6 @@ force_open (int fd, int flags)
     }
 }
 
-/* A stream that is like stderr, except line buffered.  It is NULL
-   during startup, or if line buffering is not in use.  */
-static FILE *buferr;
-
 /* Make sure stdin, stdout, and stderr are open to something, so that
    their file descriptors are not hijacked by later system calls.  */
 void
@@ -249,12 +245,10 @@ init_standard_fds (void)
   force_open (STDOUT_FILENO, O_RDONLY);
   force_open (STDERR_FILENO, O_RDONLY);
 
-  /* Set buferr if possible on platforms defining _PC_PIPE_BUF, as
+  /* Make stderr line buffered on platforms defining _PC_PIPE_BUF, as
      they support the notion of atomic writes to pipes.  */
   #ifdef _PC_PIPE_BUF
-    buferr = fdopen (STDERR_FILENO, "w");
-    if (buferr)
-      setvbuf (buferr, NULL, _IOLBF, 0);
+    setlinebuf (stderr);
   #endif
 }
 
@@ -2650,11 +2644,11 @@ safe_strsignal (int code)
 static FILE *
 errstream (void)
 {
-  FILE *err = buferr;
-  if (!err)
-    return stderr;
+#ifdef _PC_PIPE_BUF
+  /* flush line buffered stderr */
   fflush_unlocked (stderr);
-  return err;
+#endif
+  return stderr;
 }
 
 /* These functions are like fputc, vfprintf, and fwrite,
@@ -2696,9 +2690,12 @@ close_output_streams (void)
       _exit (EXIT_FAILURE);
     }
 
+  bool err;
+#ifdef _PC_PIPE_BUF
+  err = (fflush (stderr) != 0 || ferror (stderr));
+#endif
   /* Do not close stderr if addresses are being sanitized, as the
      sanitizer might report to stderr after this function is invoked.  */
-  bool err = buferr && (fflush (buferr) != 0 || ferror (buferr));
   if (err | (ADDRESS_SANITIZER
 	     ? fflush (stderr) != 0 || ferror (stderr)
 	     : close_stream (stderr) != 0))