aboutsummaryrefslogtreecommitdiffstats
path: root/src/sysdep.c
diff options
context:
space:
mode:
authorPaul Eggert2019-07-13 09:39:09 -0700
committerPaul Eggert2019-07-13 16:53:21 -0700
commita8ffbb20da67b20a85ddca38e20c609144c3bef3 (patch)
tree3ce64362d7d1a8b14f0a5ea4286ea6af27109de2 /src/sysdep.c
parent3767628dc534e64cdc21bdff16d5dd4726feacd2 (diff)
downloademacs-a8ffbb20da67b20a85ddca38e20c609144c3bef3.tar.gz
emacs-a8ffbb20da67b20a85ddca38e20c609144c3bef3.zip
Avoid interleaving stderr in a few cases
* src/sysdep.c (buferr): New static var. (init_standard_fds) [_PC_PIPE_BUF]: Initialize it. (errstream, errputc, verrprintf, errwrite): New functions. (close_output_streams): Check buferr status too. * src/xdisp.c: Include sysstdio.h instead of stdio.h. (message_to_stderr, vmessage): Use the new functions to avoid interleaving stderr.
Diffstat (limited to 'src/sysdep.c')
-rw-r--r--src/sysdep.c59
1 files changed, 56 insertions, 3 deletions
diff --git a/src/sysdep.c b/src/sysdep.c
index 99d3ee60698..4c3d546962c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -232,6 +232,10 @@ force_open (int fd, int flags)
232 } 232 }
233} 233}
234 234
235/* A stream that is like stderr, except line buffered. It is NULL
236 during startup, or if line buffering is not in use. */
237static FILE *buferr;
238
235/* Make sure stdin, stdout, and stderr are open to something, so that 239/* Make sure stdin, stdout, and stderr are open to something, so that
236 their file descriptors are not hijacked by later system calls. */ 240 their file descriptors are not hijacked by later system calls. */
237void 241void
@@ -244,6 +248,14 @@ init_standard_fds (void)
244 force_open (STDIN_FILENO, O_WRONLY); 248 force_open (STDIN_FILENO, O_WRONLY);
245 force_open (STDOUT_FILENO, O_RDONLY); 249 force_open (STDOUT_FILENO, O_RDONLY);
246 force_open (STDERR_FILENO, O_RDONLY); 250 force_open (STDERR_FILENO, O_RDONLY);
251
252 /* Set buferr if possible on platforms defining _PC_PIPE_BUF, as
253 they support the notion of atomic writes to pipes. */
254 #ifdef _PC_PIPE_BUF
255 buferr = fdopen (STDERR_FILENO, "w");
256 if (buferr)
257 setvbuf (buferr, NULL, _IOLBF, 0);
258 #endif
247} 259}
248 260
249/* Return the current working directory. The result should be freed 261/* Return the current working directory. The result should be freed
@@ -2769,6 +2781,46 @@ safe_strsignal (int code)
2769 return signame; 2781 return signame;
2770} 2782}
2771 2783
2784/* Output to stderr. */
2785
2786/* Return the error output stream. */
2787static FILE *
2788errstream (void)
2789{
2790 FILE *err = buferr;
2791 if (!err)
2792 return stderr;
2793 fflush_unlocked (stderr);
2794 return err;
2795}
2796
2797/* These functions are like fputc, vfprintf, and fwrite,
2798 except that they output to stderr and buffer better on
2799 platforms that support line buffering. This avoids interleaving
2800 output when Emacs and other processes write to stderr
2801 simultaneously, so long as the lines are short enough. When a
2802 single diagnostic is emitted via a sequence of calls of one or more
2803 of these functions, the caller should arrange for the last called
2804 function to output a newline at the end. */
2805
2806void
2807errputc (int c)
2808{
2809 fputc_unlocked (c, errstream ());
2810}
2811
2812void
2813verrprintf (char const *fmt, va_list ap)
2814{
2815 vfprintf (errstream (), fmt, ap);
2816}
2817
2818void
2819errwrite (void const *buf, ptrdiff_t nbuf)
2820{
2821 fwrite_unlocked (buf, 1, nbuf, errstream ());
2822}
2823
2772/* Close standard output and standard error, reporting any write 2824/* Close standard output and standard error, reporting any write
2773 errors as best we can. This is intended for use with atexit. */ 2825 errors as best we can. This is intended for use with atexit. */
2774void 2826void
@@ -2782,9 +2834,10 @@ close_output_streams (void)
2782 2834
2783 /* Do not close stderr if addresses are being sanitized, as the 2835 /* Do not close stderr if addresses are being sanitized, as the
2784 sanitizer might report to stderr after this function is invoked. */ 2836 sanitizer might report to stderr after this function is invoked. */
2785 if (ADDRESS_SANITIZER 2837 bool err = buferr && (fflush (buferr) != 0 || ferror (buferr));
2786 ? fflush (stderr) != 0 || ferror (stderr) 2838 if (err | (ADDRESS_SANITIZER
2787 : close_stream (stderr) != 0) 2839 ? fflush (stderr) != 0 || ferror (stderr)
2840 : close_stream (stderr) != 0))
2788 _exit (EXIT_FAILURE); 2841 _exit (EXIT_FAILURE);
2789} 2842}
2790 2843