Fix Savannah bug # 1328: if stdout is redirected to a full filesystem, we

check for this and exit with an error.
The closeout.c version from gnulib pulls in too much other stuff, and
gnulib requires an ANSI C 89 compliant compiler, while GNU make (so far)
still wants to work on K&R.
This commit is contained in:
Paul Smith 2005-06-12 22:22:07 +00:00
parent 974d14ac4f
commit 467115baae
8 changed files with 84 additions and 6 deletions

View File

@ -1,7 +1,18 @@
2005-06-12 Paul D. Smith <psmith@gnu.org>
Fix Savannah bug # 1328.
* configure.in: Check for atexit().
* misc.c (close_stdout): Test stdout to see if writes to it have
failed. If so, be sure to exit with a non-0 error code. Based on
code found in gnulib.
* make.h: Prototype.
* main.c (main): Install close_stdout() with atexit().
2005-06-10 Paul D. Smith <psmith@gnu.org>
VMS build updates from Hartmut Becker <Hartmut.Becker@hp.com>:
* vmsjobs.c [VMS]: Updates to compile on VMS: add some missing
headers; make vmsWaitForChildren() static; extern vmsify().
* job.c [VMS]: Move vmsWaitForChildren() prototype to be global.

View File

@ -137,7 +137,7 @@ AC_CHECK_FUNCS( memcpy memmove strchr strdup mkstemp mktemp fdopen \
bsd_signal dup2 getcwd realpath sigsetmask sigaction \
getgroups seteuid setegid setlinebuf setreuid setregid \
getrlimit setrlimit setvbuf pipe strerror strsignal \
lstat readlink)
lstat readlink atexit)
AC_FUNC_SETVBUF_REVERSED

View File

@ -9385,7 +9385,7 @@ foolib(hack.o) : hack.o
@end example
In fact, nearly all archive member targets are updated in just this way
and there is an implicit rule to do it for you. @strong{Note:} The
and there is an implicit rule to do it for you. @strong{Please note:} The
@samp{c} flag to @code{ar} is required if the archive file does not
already exist.

5
main.c
View File

@ -914,6 +914,10 @@ main (int argc, char **argv, char **envp)
}
#endif
#ifdef HAVE_ATEXIT
atexit (close_stdout);
#endif
/* Needed for OS/2 */
initialize_main(&argc, &argv);
@ -2176,6 +2180,7 @@ main (int argc, char **argv, char **envp)
die (status);
}
/* NOTREACHED */
return 0;
}

5
make.h
View File

@ -459,8 +459,9 @@ extern void user_access PARAMS ((void));
extern void make_access PARAMS ((void));
extern void child_access PARAMS ((void));
extern char *
strip_whitespace PARAMS ((const char **begpp, const char **endpp));
extern void close_stdout PARAMS ((void));
extern char *strip_whitespace PARAMS ((const char **begpp, const char **endpp));
#ifdef HAVE_VFORK_H

47
misc.c
View File

@ -823,3 +823,50 @@ get_path_max (void)
return value;
}
#endif
/* 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. */
void
close_stdout (void)
{
int prev_fail = ferror (stdout);
int fclose_fail = fclose (stdout);
if (prev_fail || fclose_fail)
{
if (fclose_fail)
error (NILF, _("write error: %s"), strerror (errno));
else
error (NILF, _("write error"));
exit (EXIT_FAILURE);
}
}

View File

@ -1,3 +1,8 @@
2005-06-12 Paul D. Smith <psmith@gnu.org>
* scripts/misc/close_stdout: Add a test for Savannah bug #1328.
This test only works on systems that have /dev/full (e.g., Linux).
2005-06-09 Paul D. Smith <psmith@gnu.org>
* scripts/functions/foreach: Add a test for Savannah bug #11913.

View File

@ -0,0 +1,9 @@
# -*-perl-*-
$description = "Make sure make exits with an error if stdout is full.";
if (-e '/dev/full') {
run_make_test('', '-v > /dev/full', '#MAKE#: write error', 256);
}
1;