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;
     }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.