Re: add some fd tests to head
Eric Blake <[email protected]>
| Newsgroups | gmane.comp.gnu.m4.patches |
|---|---|
| Message-ID | <[email protected]> |
Eric Blake <ebb9 <at> byu.net> writes: > > 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). My clean-temp usage is still buggy on mingw and cygwin. m4exit tried to remove the temporary directory while spilled diversions had open file descriptors, which is a no-no on Windows. This is the patch for head; I'll have to backport it to the branch before 1.4.8: 2006-11-07 Eric Blake <[email protected]> * tests/builtins.at (m4exit): New test; failed on cygwin before this patch. * m4/output.c (cleanup_tmpfile): Close files before removing directory. (make_room_for): Ensure that m4_error sees consistent state. Index: tests/builtins.at =================================================================== RCS file: /sources/m4/m4/tests/builtins.at,v retrieving revision 1.31 diff -u -r1.31 builtins.at --- tests/builtins.at 7 Nov 2006 19:18:10 -0000 1.31 +++ tests/builtins.at 8 Nov 2006 00:15:56 -0000 @@ -545,6 +545,25 @@ AT_CLEANUP +## ------ ## +## m4exit ## +## ------ ## + +AT_SETUP([m4exit]) + +dnl Ensure that spilled diversions are gracefully cleaned up +AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f +m4exit +]]) +AT_CHECK([rm -Rf tmpdir && mkdir tmpdir && test -d tmpdir]) +TMPDIR=tmpdir +export TMPDIR +AT_CHECK_M4([in.m4], [0]) +AT_CHECK([rmdir tmpdir]) + +AT_CLEANUP + + ## ------- ## ## mkdtemp ## ## ------- ## Index: m4/output.c =================================================================== RCS file: /sources/m4/m4/m4/output.c,v retrieving revision 1.35 diff -u -r1.35 output.c --- m4/output.c 27 Oct 2006 04:03:28 -0000 1.35 +++ m4/output.c 8 Nov 2006 00:15:56 -0000 @@ -165,6 +165,25 @@ static void cleanup_tmpfile (void) { + /* Close any open diversions. */ + m4_diversion *diversion; + gl_list_iterator_t iter; + const void *elt; + + if (diversion_table) + { + iter = gl_list_iterator_from_to (diversion_table, 1, + gl_list_size (diversion_table)); + while (gl_list_iterator_next (&iter, &elt, NULL)) + { + diversion = (m4_diversion *) elt; + if (!diversion->size && diversion->u.file) + close_stream_temp (diversion->u.file); + } + gl_list_iterator_free (&iter); + } + + /* Clean up the temporary directory. */ if (cleanup_temp_dir (output_temp_dir) != 0) _exit (exit_failure); } @@ -263,10 +282,15 @@ gl_list_iterator_free (&iter); /* Create a temporary file, write the in-memory buffer of the - diversion to this file, then release the buffer. */ + diversion to this file, then release the buffer. Set the + size to zero before doing anything that can exit (), so that + the atexit handler recognizes a file that must be closed. */ selected_buffer = selected_diversion->u.buffer; selected_diversion->u.file = m4_tmpfile (context); + total_buffer_size -= selected_diversion->size; + selected_diversion->size = 0; + if (set_cloexec_flag (fileno (selected_diversion->u.file), true) != 0) m4_error (context, 0, errno, _("cannot protect diversion across forks")); @@ -283,9 +307,6 @@ /* Reclaim the buffer space for other diversions. */ free (selected_buffer); - total_buffer_size -= selected_diversion->size; - - selected_diversion->size = 0; selected_diversion->used = 0; }