summaryrefslogtreecommitdiff
path: root/src/output.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2022-08-30 09:02:33 -0400
committerPaul Smith <psmith@gnu.org>2022-08-30 21:04:48 -0400
commit26e359c71d1758ea1f6ac43f1d1591254d1bf0c2 (patch)
tree6d5166eac58ad77c88b5a89432769e454280113b /src/output.c
parent4da2055a10bd21b4e34f1b650484f0636d3b3ca2 (diff)
downloadmake-git-26e359c71d1758ea1f6ac43f1d1591254d1bf0c2.tar.gz
[SV 62840] Don't change IO buffering before printing version
If users run 'make --version | head -n1' they expect make to exit with a success (0) code. This works because the pipe forces the default buffering on stdout to be fully buffered so all the output is printed to the pipe in a single write(2) and won't fail. However due to output sync we forcibly set stdout to line buffered, which means if the reader closes the pipe fast enough make will exit with an error code because the write to stdout failed. Move the setup done in output_init() back into main() where it can be done in a proper order. Rework the order of operations during startup so that we check for help and version flags before we change the buffering. Clean up the behavior of print_usage(). Original changes from Dmitry Goncharov <dgoncharov@users.sf.net>. * src/main.c (switches): Don't send --version in the environment. (print_usage): Add a blank line after the version before the usage. Move the die() into this function since we always die() afterward. Note the die will flush so no need to do it explicitly. (print_version): The caller will fflush when appropriate. (close_stdout): Move from output.c so it is installed early. (decode_switches): Only call print_usage on error, not for --help. (main): Install the close_stdout handler immediately after start. Move the calls to print_usage() due to --help and --version to be called immediately after we decode the switches. Move the buffer set here from output_init(), immediately after we know we'll be running. * src/output.c (output_init): Move buffer setting to main(). (close_stdout): Move to main().
Diffstat (limited to 'src/output.c')
-rw-r--r--src/output.c64
1 files changed, 2 insertions, 62 deletions
diff --git a/src/output.c b/src/output.c
index 91a1dc31..d806159f 100644
--- a/src/output.c
+++ b/src/output.c
@@ -299,53 +299,6 @@ output_dump (struct output *out)
#endif /* NO_OUTPUT_SYNC */
-/* This code is stolen from gnulib.
- If/when we abandon the requirement to work with K&R compilers, we can
- remove this (and perhaps other parts of GNU make!) and migrate to using
- gnulib directly.
-
- This is called only through atexit(), which means die() has already been
- invoked. So, call exit() here directly. Apparently that works...?
-*/
-
-/* Close standard output, exiting with status 'exit_failure' on failure.
- If a program writes *anything* to stdout, that program should close
- stdout and make sure that it succeeds before exiting. Otherwise,
- suppose that you go to the extreme of checking the return status
- of every function that does an explicit write to stdout. The last
- printf can succeed in writing to the internal stream buffer, and yet
- the fclose(stdout) could still fail (due e.g., to a disk full error)
- when it tries to write out that buffered data. Thus, you would be
- left with an incomplete output file and the offending program would
- exit successfully. Even calling fflush is not always sufficient,
- since some file systems (NFS and CODA) buffer written/flushed data
- until an actual close call.
-
- Besides, it's wasteful to check the return value from every call
- that writes to stdout -- just let the internal stream state record
- the failure. That's what the ferror test is checking below.
-
- It's important to detect such failures and exit nonzero because many
- tools (most notably 'make' and other build-management systems) depend
- on being able to detect failure in other tools via their exit status. */
-
-static void
-close_stdout (void)
-{
- int prev_fail = ferror (stdout);
- int fclose_fail = fclose (stdout);
-
- if (prev_fail || fclose_fail)
- {
- if (fclose_fail)
- perror_with_name (_("write error: stdout"), "");
- else
- O (error, NILF, _("write error: stdout"));
- exit (MAKE_TROUBLE);
- }
-}
-
-
void
output_init (struct output *out)
{
@@ -356,23 +309,10 @@ output_init (struct output *out)
return;
}
- /* Configure this instance of make. Be sure stdout is line-buffered. */
-
-#ifdef HAVE_SETVBUF
- setvbuf (stdout, 0, _IOLBF, BUFSIZ);
-#elif HAVE_SETLINEBUF
- setlinebuf (stdout);
-#endif /* setlinebuf missing. */
-
- /* Force stdout/stderr into append mode. This ensures parallel jobs won't
- lose output due to overlapping writes. */
+ /* Force stdout/stderr into append mode (if they are files) to ensure
+ parallel jobs won't lose output due to overlapping writes. */
fd_set_append (fileno (stdout));
fd_set_append (fileno (stderr));
-
-#ifdef HAVE_ATEXIT
- if (ANY_SET (check_io_state (), IO_STDOUT_OK))
- atexit (close_stdout);
-#endif
}
void