Create an open_tmpfd() function to return temp files by FD. Use it.

This commit is contained in:
Paul Smith 2013-04-16 00:35:48 -04:00
parent 79e9347892
commit b5d017c624
8 changed files with 110 additions and 105 deletions

View File

@ -41,6 +41,7 @@ GNU make porting efforts:
Jonathan Grant <jg@jguk.org> Jonathan Grant <jg@jguk.org>
Andreas Beuning <andreas.buening@nexgo.de> Andreas Beuning <andreas.buening@nexgo.de>
Earnie Boyd <earnie@uses.sf.net> Earnie Boyd <earnie@uses.sf.net>
Troy Runkel <Troy.Runkel@mathworks.com>
----------------------------------- -----------------------------------
Other contributors: Other contributors:
@ -64,6 +65,8 @@ Other contributors:
Carl Staelin (Princeton University) Carl Staelin (Princeton University)
Ian Stewartson (Data Logic Limited) Ian Stewartson (Data Logic Limited)
David A. Wheeler <dwheeler@dwheeler.com> David A. Wheeler <dwheeler@dwheeler.com>
David Boyce <dsb@boyski.com>
Frank Heckenbach <f.heckenbach@fh-soft.de>
With suggestions/comments/bug reports from a cast of ... well ... With suggestions/comments/bug reports from a cast of ... well ...
hundreds, anyway :) hundreds, anyway :)

View File

@ -1,3 +1,10 @@
2013-04-16 Paul Smith <psmith@gnu.org>
* misc.c (open_tmpfd): Add a new function that returns a temporary
file by file descriptor.
(open_tmpfile): Move here from main.c.
* job.c (assign_child_tempfiles): Use the new open_tmpfd().
2013-04-15 Paul Smith <psmith@gnu.org> 2013-04-15 Paul Smith <psmith@gnu.org>
* makeint.h (OUTPUT_SYNC_TARGET, OUTPUT_SYNC_MAKE): Rename. * makeint.h (OUTPUT_SYNC_TARGET, OUTPUT_SYNC_MAKE): Rename.

10
NEWS
View File

@ -1,6 +1,6 @@
GNU make NEWS -*-indented-text-*- GNU make NEWS -*-indented-text-*-
History of user-visible changes. History of user-visible changes.
05 March 2012 16 April 2013
See the end of this file for copyrights and conditions. See the end of this file for copyrights and conditions.
@ -9,7 +9,7 @@ manual, which is contained in this distribution as the file doc/make.texi.
See the README file and the GNU make manual for instructions for See the README file and the GNU make manual for instructions for
reporting bugs. reporting bugs.
Version 3.99.90 Version 3.82.90
A complete list of bugs fixed in this version is available here: A complete list of bugs fixed in this version is available here:
@ -29,6 +29,12 @@ http://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=101&set
makefile name and linenumber where it was defined are shown as well as the makefile name and linenumber where it was defined are shown as well as the
prerequisites that caused the target to be considered out of date. prerequisites that caused the target to be considered out of date.
* New command line option: --output-sync (-O) enables grouping of output by
target or by recursive make. This is useful during parallel builds to avoid
mixing output from different jobs together giving hard-to-understand results.
Original implementation by David Boyce <dsb@boyski.com>. Patch was reworked
by Frank Heckenbach <f.heckenbach@fh-soft.de>.
* New feature: The "job server" capability is now supported on Windows. * New feature: The "job server" capability is now supported on Windows.
Implementation contributed by Troy Runkel <Troy.Runkel@mathworks.com> Implementation contributed by Troy Runkel <Troy.Runkel@mathworks.com>

63
job.c
View File

@ -558,7 +558,6 @@ static int
assign_child_tempfiles (struct child *c, int combined) assign_child_tempfiles (struct child *c, int combined)
{ {
FILE *outstrm = NULL, *errstrm = NULL; FILE *outstrm = NULL, *errstrm = NULL;
int o_ok, e_ok;
const char *suppressed = "output-sync suppressed: "; const char *suppressed = "output-sync suppressed: ";
char *failmode = NULL; char *failmode = NULL;
@ -566,70 +565,24 @@ assign_child_tempfiles (struct child *c, int combined)
if (c->outfd != -1 && c->errfd != -1) if (c->outfd != -1 && c->errfd != -1)
return 1; return 1;
/* Check status of stdout and stderr before hooking up temp files. */ if (STREAM_OK (stdout))
o_ok = STREAM_OK (stdout);
e_ok = STREAM_OK (stderr);
/* The tmpfile() function returns a FILE pointer but those can be in
limited supply, so we immediately dup its file descriptor and keep
only that, closing the FILE pointer. */
if (combined)
{ {
if (!(outstrm = tmpfile ())) c->outfd = open_tmpfd ();
failmode = "tmpfile()"; CLOSE_ON_EXEC (c->outfd);
else
errstrm = outstrm;
}
else if (o_ok && e_ok)
{
if (!(outstrm = tmpfile ()) || !(errstrm = tmpfile ()))
failmode = "tmpfile()";
}
else if (o_ok)
{
if (!(outstrm = tmpfile ()))
failmode = "tmpfile()";
}
else if (e_ok)
{
if (!(errstrm = tmpfile ()))
failmode = "tmpfile()";
}
else
failmode = "stdout";
if (!failmode && outstrm)
{
if ((c->outfd = dup (fileno (outstrm))) == -1)
failmode = "dup2()";
else
CLOSE_ON_EXEC (c->outfd);
} }
if (!failmode && errstrm) if (STREAM_OK (stderr))
{ {
if (combined) if (c->outfd >= 0 && combined)
c->errfd = c->outfd; c->errfd = c->outfd;
else else
{ {
if ((c->errfd = dup (fileno (errstrm))) == -1) c->errfd = open_tmpfd ();
failmode = "dup2()"; CLOSE_ON_EXEC (c->errfd);
else
CLOSE_ON_EXEC (c->errfd);
} }
} }
if (failmode) return 1;
perror_with_name (suppressed, failmode);
if (outstrm)
(void) fclose (outstrm);
if (errstrm && errstrm != outstrm)
(void) fclose (errstrm);
return failmode == NULL;
} }
/* Support routine for sync_output() */ /* Support routine for sync_output() */

4
job.h
View File

@ -34,10 +34,6 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
# define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC) # define CLOSE_ON_EXEC(_d) (void) fcntl ((_d), F_SETFD, FD_CLOEXEC)
#endif #endif
#ifdef POSIX
# define OUTPUT_SYNC
#endif
/* Structure describing a running or dead child process. */ /* Structure describing a running or dead child process. */
struct child struct child

44
main.c
View File

@ -907,50 +907,6 @@ msdos_return_to_initial_directory (void)
} }
#endif /* __MSDOS__ */ #endif /* __MSDOS__ */
char *mktemp (char *template);
int mkstemp (char *template);
FILE *
open_tmpfile(char **name, const char *template)
{
#ifdef HAVE_FDOPEN
int fd;
#endif
#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
# define TEMPLATE_LEN strlen (template)
#else
# define TEMPLATE_LEN L_tmpnam
#endif
*name = xmalloc (TEMPLATE_LEN + 1);
strcpy (*name, template);
#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
/* It's safest to use mkstemp(), if we can. */
fd = mkstemp (*name);
if (fd == -1)
return 0;
return fdopen (fd, "w");
#else
# ifdef HAVE_MKTEMP
(void) mktemp (*name);
# else
(void) tmpnam (*name);
# endif
# ifdef HAVE_FDOPEN
/* Can't use mkstemp(), but guard against a race condition. */
fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd == -1)
return 0;
return fdopen (fd, "w");
# else
/* Not secure, but what can we do? */
return fopen (*name, "w");
# endif
#endif
}
#ifdef _AMIGA #ifdef _AMIGA
int int
main (int argc, char **argv) main (int argc, char **argv)

View File

@ -413,6 +413,7 @@ int alpha_compare (const void *, const void *);
void print_spaces (unsigned int); void print_spaces (unsigned int);
char *find_percent (char *); char *find_percent (char *);
const char *find_percent_cached (const char **); const char *find_percent_cached (const char **);
int open_tmpfd (void);
FILE *open_tmpfile (char **, const char *); FILE *open_tmpfile (char **, const char *);
#ifndef NO_ARCHIVES #ifndef NO_ARCHIVES
@ -525,6 +526,10 @@ int strncasecmp (const char *s1, const char *s2, int n);
# endif # endif
#endif #endif
#ifdef POSIX
# define OUTPUT_SYNC
#endif
#define OUTPUT_SYNC_TARGET 1 #define OUTPUT_SYNC_TARGET 1
#define OUTPUT_SYNC_MAKE 2 #define OUTPUT_SYNC_MAKE 2

79
misc.c
View File

@ -930,6 +930,85 @@ get_path_max (void)
#endif #endif
/* Provide support for temporary files. */
#ifndef HAVE_STDLIB_H
# ifdef HAVE_MKSTEMP
int mkstemp (char *template);
# else
char *mktemp (char *template);
# endif
#endif
/* This is only used by output-sync, and it may not be portable to Windows. */
#ifdef OUTPUT_SYNC
/* Returns a file descriptor to a temporary file. The file is automatically
closed/deleted on exit. Don't use a FILE* stream. */
int
open_tmpfd()
{
int fd = -1;
FILE *tfile = tmpfile();
if (! tfile)
pfatal_with_name ("tmpfile");
/* Create a duplicate so we can close the stream. */
fd = dup (fileno (tfile));
if (fd < 0)
pfatal_with_name ("dup");
fclose (tfile);
return fd;
}
#endif
FILE *
open_tmpfile(char **name, const char *template)
{
#ifdef HAVE_FDOPEN
int fd;
#endif
#if defined HAVE_MKSTEMP || defined HAVE_MKTEMP
# define TEMPLATE_LEN strlen (template)
#else
# define TEMPLATE_LEN L_tmpnam
#endif
*name = xmalloc (TEMPLATE_LEN + 1);
strcpy (*name, template);
#if defined HAVE_MKSTEMP && defined HAVE_FDOPEN
/* It's safest to use mkstemp(), if we can. */
fd = mkstemp (*name);
if (fd == -1)
return 0;
return fdopen (fd, "w");
#else
# ifdef HAVE_MKTEMP
(void) mktemp (*name);
# else
(void) tmpnam (*name);
# endif
# ifdef HAVE_FDOPEN
/* Can't use mkstemp(), but guard against a race condition. */
fd = open (*name, O_CREAT|O_EXCL|O_WRONLY, 0600);
if (fd == -1)
return 0;
return fdopen (fd, "w");
# else
/* Not secure, but what can we do? */
return fopen (*name, "w");
# endif
#endif
}
/* This code is stolen from gnulib. /* This code is stolen from gnulib.
If/when we abandon the requirement to work with K&R compilers, we can 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 remove this (and perhaps other parts of GNU make!) and migrate to using