aboutsummaryrefslogtreecommitdiffstats
path: root/src
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
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')
-rw-r--r--src/sysdep.c59
-rw-r--r--src/sysstdio.h3
-rw-r--r--src/xdisp.c19
3 files changed, 63 insertions, 18 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
diff --git a/src/sysstdio.h b/src/sysstdio.h
index 68ae043fe33..5303e8a15b2 100644
--- a/src/sysstdio.h
+++ b/src/sysstdio.h
@@ -25,6 +25,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
25#include "unlocked-io.h" 25#include "unlocked-io.h"
26 26
27extern FILE *emacs_fopen (char const *, char const *); 27extern FILE *emacs_fopen (char const *, char const *);
28extern void errputc (int);
29extern void verrprintf (char const *, va_list) ATTRIBUTE_FORMAT_PRINTF (1, 0);
30extern void errwrite (void const *, ptrdiff_t);
28extern void close_output_streams (void); 31extern void close_output_streams (void);
29 32
30#if O_BINARY 33#if O_BINARY
diff --git a/src/xdisp.c b/src/xdisp.c
index 7f0d577cebc..50f6443f6b2 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -10714,7 +10714,7 @@ message_to_stderr (Lisp_Object m)
10714 if (noninteractive_need_newline) 10714 if (noninteractive_need_newline)
10715 { 10715 {
10716 noninteractive_need_newline = false; 10716 noninteractive_need_newline = false;
10717 putc ('\n', stderr); 10717 errputc ('\n');
10718 } 10718 }
10719 if (STRINGP (m)) 10719 if (STRINGP (m))
10720 { 10720 {
@@ -10728,21 +10728,10 @@ message_to_stderr (Lisp_Object m)
10728 else 10728 else
10729 s = m; 10729 s = m;
10730 10730
10731 /* We want to write this out with a single call so that 10731 errwrite (SDATA (s), SBYTES (s));
10732 output doesn't interleave with other processes writing to
10733 stderr at the same time. */
10734 {
10735 int length = min (INT_MAX, SBYTES (s) + 1);
10736 char *string = xmalloc (length);
10737
10738 memcpy (string, SSDATA (s), length - 1);
10739 string[length - 1] = '\n';
10740 fwrite (string, 1, length, stderr);
10741 xfree (string);
10742 }
10743 } 10732 }
10744 else if (!cursor_in_echo_area) 10733 if (STRINGP (m) || !cursor_in_echo_area)
10745 putc ('\n', stderr); 10734 errputc ('\n');
10746} 10735}
10747 10736
10748/* The non-logging version of message3. 10737/* The non-logging version of message3.