[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: add some fd tests to head
From: |
Eric Blake |
Subject: |
Re: add some fd tests to head |
Date: |
Fri, 13 Oct 2006 22:25:10 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Eric Blake <ebb9 <at> byu.net> writes:
>
> 2006-10-06 Eric Blake <ebb9 <at> byu.net>
>
> Replace uses of tmpfile with clean-temp, since tmpfile is
> incompatible with closeout.
This was relatively easy to port to the branch (although it breaks mingw builds
unless a pending patch of mine is accepted in gnulib).
2006-10-13 Eric Blake <address@hidden>
Backport head's usage of clean-temp module, as it is cleaner than
using tmpfile-safer.
* m4/gnulib-cache.m4: Augment with 'gnulib-tool --import
clean-temp closeout', and remove tmpfile-safer.
* src/m4.h (includes): Adjust.
(m4_path_search): Rename from path_search, to avoid collision
with gnulib.
* src/m4.c (main): Install closeout handler. Adjust caller.
(usage): Now done by closeout module.
* src/builtin.c (m4_m4exit): Likewise.
(m4_undivert, include): Adjust callers.
* src/freeze.c (reload_frozen_state): Likewise.
* src/path.c (m4_path_search): Rename from path_search.
* src/output.c (output_temp_dir): New variable.
(cleanup_tmpfile, m4_tmpfile): New functions, from head.
(insert_diversion, make_room_for): Use them.
* doc/m4.texinfo (Diversions): Document this, and add a test.
(Improved fatal_error): Fix typo.
(Maketemp): Port test to mingw, and no longer hide from
documentation.
* NEWS: Document the change in TMPDIR behavior.
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.1.1.1.2.71
diff -u -r1.1.1.1.2.71 NEWS
--- NEWS 13 Oct 2006 12:59:16 -0000 1.1.1.1.2.71
+++ NEWS 13 Oct 2006 22:20:55 -0000
@@ -22,6 +22,10 @@
token in an included file.
* The `builtin' and `indir' macros now transparently handle builtin
tokens generated by `defn'.
+* When diversions created by the `divert' macro collect enough text that
+ M4 must use temporary files, the environment variable $TMPDIR is now
+ consulted, and a better effort is made to clean up those files in the
+ event of a fatal signal.
Version 1.4.7 - 25 September 2006, by Eric Blake (CVS version 1.4.6a)
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.1.1.1.2.84
diff -u -r1.1.1.1.2.84 m4.texinfo
--- doc/m4.texinfo 13 Oct 2006 12:59:17 -0000 1.1.1.1.2.84
+++ doc/m4.texinfo 13 Oct 2006 22:20:55 -0000
@@ -3240,9 +3240,46 @@
(512K, currently). When this maximum is about to be exceeded,
a temporary file is opened to receive the contents of the biggest
diversion still in memory, freeing this memory for other diversions.
+When creating the temporary file, @code{m4} honors the value of the
+environment variable @env{TMPDIR}, and falls back to @file{/tmp}.
So, it is theoretically possible that the number of diversions be
limited by the number of available file descriptors.
address@hidden
address@hidden We need to test spilled diversions, but don't need to expose
address@hidden this highly repetitive test in the manual.
+
address@hidden
+divert(`-1')define(`f', `.')
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+define(`f', defn(`f')defn(`f'))
+divert`'dnl
+len(f)
address@hidden
+divert(`1')
+f
+divert(`-1')undivert
address@hidden example
address@hidden ignore
+
@c FIXME: need some explanation here why this is a useful feature, not
@c just how you use it.
@@ -4394,16 +4431,9 @@
@code{maketemp}, so a future version of @acronym{GNU} M4 may have
changes in this area.
address@hidden
address@hidden This test makes sure maketemp gets testsuite coverage, but is
address@hidden somewhat complex for use in the manual.
@example
-dnl This test assumes /tmp is a valid directory name, which is not true
-dnl for native Windows.
-ifdef(`__unix__', , `errprint(` skipping: not sure /tmp exists
-')m4exit(`77')')dnl
-define(`file1', maketemp(`/tmp/fooXXXXXX'))dnl
-define(`file2', maketemp(`/tmp/fooXXXXXX'))dnl
+define(`file1', maketemp(`fooXXXXXX'))dnl
+define(`file2', maketemp(`fooXXXXXX'))dnl
ifelse(file1, file2, `same', `different')
@result{}different
syscmd(`rm 'file1 file2)
@@ -4411,7 +4441,6 @@
sysval
@result{}0
@end example
address@hidden ignore
@node Miscellaneous
@chapter Miscellaneous builtin macros
@@ -5189,7 +5218,7 @@
@example
define(`fatal_error',
- `errprint(ifdef(`__program', `__program__', ``m4'')'dnl
+ `errprint(ifdef(`__program__', `__program__', ``m4'')'dnl
`:ifelse(__line__, `0', `',
`__file__:__line__:')` fatal error: $*
')m4exit(`1')')
Index: m4/gnulib-cache.m4
===================================================================
RCS file: /sources/m4/m4/m4/Attic/gnulib-cache.m4,v
retrieving revision 1.1.2.15
diff -u -r1.1.2.15 gnulib-cache.m4
--- m4/gnulib-cache.m4 7 Sep 2006 22:48:15 -0000 1.1.2.15
+++ m4/gnulib-cache.m4 13 Oct 2006 22:20:55 -0000
@@ -15,11 +15,11 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --lib=libm4 --source-base=lib --m4-base=m4 --
doc-base=doc --aux-dir=. --no-libtool --macro-prefix=M4 binary-io cloexec close-
stream error fdl fopen-safer free gendocs getopt gnupload mkstemp obstack regex
stdlib-safer strtol tmpfile-safer unlocked-io verror xalloc xvasprintf
+# gnulib-tool --import --dir=. --lib=libm4 --source-base=lib --m4-base=m4 --
doc-base=doc --aux-dir=. --no-libtool --macro-prefix=M4 binary-io clean-temp
cloexec close-stream closeout error fdl fopen-safer free gendocs getopt
gnupload mkstemp obstack regex stdlib-safer strtol unlocked-io verror xalloc
xvasprintf
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([])
-gl_MODULES([binary-io cloexec close-stream error fdl fopen-safer free gendocs
getopt gnupload mkstemp obstack regex stdlib-safer strtol tmpfile-safer
unlocked-io verror xalloc xvasprintf])
+gl_MODULES([binary-io clean-temp cloexec close-stream closeout error fdl fopen-
safer free gendocs getopt gnupload mkstemp obstack regex stdlib-safer strtol
unlocked-io verror xalloc xvasprintf])
gl_AVOID([])
gl_SOURCE_BASE([lib])
gl_M4_BASE([m4])
Index: src/builtin.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/builtin.c,v
retrieving revision 1.1.1.1.2.42
diff -u -r1.1.1.1.2.42 builtin.c
--- src/builtin.c 13 Oct 2006 12:59:17 -0000 1.1.1.1.2.42
+++ src/builtin.c 13 Oct 2006 22:20:55 -0000
@@ -1088,7 +1088,7 @@
"non-numeric argument to builtin `%s'", ARG (0)));
else
{
- fp = path_search (ARG (i), NULL);
+ fp = m4_path_search (ARG (i), NULL);
if (fp != NULL)
{
insert_file (fp);
@@ -1200,7 +1200,7 @@
if (bad_argc (argv[0], argc, 2, 2))
return;
- fp = path_search (ARG (1), &name);
+ fp = m4_path_search (ARG (1), &name);
if (fp == NULL)
{
if (!silent)
@@ -1329,16 +1329,11 @@
detect any errors it might have encountered. */
debug_set_output (NULL);
debug_flush_files ();
- if (close_stream (stdout) != 0)
- {
- M4ERROR ((warning_status, errno, "write error"));
- if (exit_code == 0)
- exit_code = EXIT_FAILURE;
- }
- if (close_stream (stderr) != 0 && exit_code == 0)
- exit_code = EXIT_FAILURE;
- if (exit_code == 0 && retcode != 0)
+ if (exit_code == EXIT_SUCCESS && retcode != EXIT_SUCCESS)
exit_code = retcode;
+ /* Propagate non-zero status to atexit handlers. */
+ if (exit_code != EXIT_SUCCESS)
+ exit_failure = exit_code;
exit (exit_code);
}
Index: src/freeze.c
===================================================================
RCS file: /sources/m4/m4/src/freeze.c,v
retrieving revision 1.1.1.1.2.12
diff -u -r1.1.1.1.2.12 freeze.c
--- src/freeze.c 30 Jul 2006 03:18:12 -0000 1.1.1.1.2.12
+++ src/freeze.c 13 Oct 2006 22:20:55 -0000
@@ -222,7 +222,7 @@
} \
while (character == '\n')
- file = path_search (name, NULL);
+ file = m4_path_search (name, NULL);
if (file == NULL)
M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name));
Index: src/m4.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/m4.c,v
retrieving revision 1.1.1.1.2.33
diff -u -r1.1.1.1.2.33 m4.c
--- src/m4.c 10 Oct 2006 03:54:26 -0000 1.1.1.1.2.33
+++ src/m4.c 13 Oct 2006 22:20:55 -0000
@@ -204,11 +204,6 @@
", stdout);
printf ("\nReport bugs to <%s>.\n", PACKAGE_BUGREPORT);
}
-
- if (close_stream (stdout) != 0)
- M4ERROR ((EXIT_FAILURE, errno, "write error"));
- if (close_stream (stderr) != 0)
- exit (EXIT_FAILURE); /* Can't really do much else without stderr. */
exit (status);
}
@@ -286,6 +281,7 @@
program_name = argv[0];
retcode = EXIT_SUCCESS;
+ atexit (close_stdout);
include_init ();
debug_init ();
@@ -421,20 +417,15 @@
break;
case VERSION_OPTION:
- printf ("%s\n", PACKAGE_STRING);
- fputs ("\
+ printf ("%s\n", PACKAGE_STRING);
+ fputs ("\
Copyright (C) 2006 Free Software Foundation, Inc.\n\
This is free software; see the source for copying conditions. There is NO\n\
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
\n\
Written by Rene' Seindal.\n\
", stdout);
-
- if (close_stream (stdout) != 0)
- M4ERROR ((EXIT_FAILURE, errno, "write error"));
- if (close_stream (stderr) != 0)
- exit (EXIT_FAILURE);
- exit (EXIT_SUCCESS);
+ exit (EXIT_SUCCESS);
break;
case HELP_OPTION:
@@ -532,7 +523,7 @@
else
{
const char *name;
- fp = path_search (argv[optind], &name);
+ fp = m4_path_search (argv[optind], &name);
if (fp == NULL)
{
error (0, errno, "%s", argv[optind]);
@@ -570,10 +561,5 @@
make_diversion (0);
undivert_all ();
}
-
- if (close_stream (stdout) != 0)
- M4ERROR ((EXIT_FAILURE, errno, "write error"));
- if (close_stream (stderr) != 0)
- exit (EXIT_FAILURE); /* Can't really do much else without stderr. */
exit (retcode);
}
Index: src/m4.h
===================================================================
RCS file: /sources/m4/m4/src/m4.h,v
retrieving revision 1.1.1.1.2.29
diff -u -r1.1.1.1.2.29 m4.h
--- src/m4.h 7 Sep 2006 22:48:15 -0000 1.1.1.1.2.29
+++ src/m4.h 13 Oct 2006 22:20:55 -0000
@@ -49,16 +49,20 @@
#include <sys/types.h>
#include "binary-io.h"
+#include "clean-temp.h"
#include "cloexec.h"
#include "close-stream.h"
+#include "closeout.h"
#include "error.h"
#include "exit.h"
+#include "exitfail.h"
#include "obstack.h"
#include "stdio--.h"
#include "stdlib--.h"
#include "unistd--.h"
#include "verror.h"
#include "xalloc.h"
+#include "xvasprintf.h"
/* If FALSE is defined, we presume TRUE is defined too. In this case,
merely typedef boolean as being int. Or else, define these all. */
@@ -418,7 +422,7 @@
void include_init (void);
void include_env_init (void);
void add_include_directory (const char *);
-FILE *path_search (const char *, const char **);
+FILE *m4_path_search (const char *, const char **);
/* File: eval.c --- expression evaluation. */
Index: src/output.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/output.c,v
retrieving revision 1.1.1.1.2.10
diff -u -r1.1.1.1.2.10 output.c
--- src/output.c 18 Aug 2006 23:11:37 -0000 1.1.1.1.2.10
+++ src/output.c 13 Oct 2006 22:20:56 -0000
@@ -76,6 +76,13 @@
/* Number of input line we are generating output for. */
int output_current_line;
+
+typedef struct temp_dir m4_temp_dir;
+
+/* Temporary directory holding all spilled diversion files. */
+static m4_temp_dir *output_temp_dir;
+
+
/*------------------------.
| Output initialisation. |
@@ -99,6 +106,48 @@
output_unused = 0;
}
+/* Clean up any temporary directory. Designed for use as an atexit
+ handler, where it is not safe to call exit() recursively; so this
+ calls _exit if a problem is encountered. */
+static void
+cleanup_tmpfile (void)
+{
+ if (cleanup_temp_dir (output_temp_dir) != 0)
+ _exit (exit_failure);
+}
+
+/* Create a temporary file open for reading and writing in a secure
+ temp directory. The file will be automatically closed and deleted
+ on a fatal signal. When done with the file, close it with
+ close_stream_temp. Exits on failure, so the return value is always
+ an open file. */
+static FILE *
+m4_tmpfile (void)
+{
+ static unsigned int count;
+ char *name;
+ FILE *file;
+
+ if (output_temp_dir == NULL)
+ {
+ errno = 0;
+ output_temp_dir = create_temp_dir ("m4-", NULL, true);
+ if (output_temp_dir == NULL)
+ M4ERROR ((EXIT_FAILURE, errno,
+ "cannot create temporary file for diversion"));
+ atexit (cleanup_tmpfile);
+ }
+ name = xasprintf ("%s/m4-%d", output_temp_dir->dir_name, count++);
+ register_temp_file (output_temp_dir, name);
+ errno = 0;
+ file = fopen_temp (name, O_BINARY ? "wb+" : "w+");
+ if (file == NULL)
+ M4ERROR ((EXIT_FAILURE, errno,
+ "cannot create temporary file for diversion"));
+ free (name);
+ return file;
+}
+
/*-----------------------------------------------------------------------.
| Reorganize in-memory diversion buffers so the current diversion can |
| accomodate LENGTH more characters without further reorganization. The |
@@ -154,10 +203,7 @@
/* Create a temporary file, write the in-memory buffer of the
diversion to this file, then release the buffer. */
- selected_diversion->file = tmpfile ();
- if (selected_diversion->file == NULL)
- M4ERROR ((EXIT_FAILURE, errno,
- "ERROR: cannot create temporary file for diversion"));
+ selected_diversion->file = m4_tmpfile ();
if (set_cloexec_flag (fileno (selected_diversion->file), true) != 0)
M4ERROR ((warning_status, errno,
"Warning: cannot protect diversion across forks"));
@@ -485,7 +531,7 @@
if (diversion->file)
{
- fclose (diversion->file);
+ close_stream_temp (diversion->file);
diversion->file = NULL;
}
else if (diversion->buffer)
Index: src/path.c
===================================================================
RCS file: /sources/m4/m4/src/Attic/path.c,v
retrieving revision 1.1.1.1.2.11
diff -u -r1.1.1.1.2.11 path.c
--- src/path.c 10 Oct 2006 11:36:40 -0000 1.1.1.1.2.11
+++ src/path.c 13 Oct 2006 22:20:56 -0000
@@ -111,7 +111,7 @@
respect to the current working directory. */
FILE *
-path_search (const char *file, const char **result)
+m4_path_search (const char *file, const char **result)
{
FILE *fp;
includes *incl;
@@ -154,7 +154,7 @@
strcpy (name + incl->len + 1, file);
#ifdef DEBUG_INCL
- fprintf (stderr, "path_search (%s) -- trying %s\n", file, name);
+ fprintf (stderr, "m4_path_search (%s) -- trying %s\n", file, name);
#endif
fp = fopen (name, "r");