PATCH COMMITTED: Fix for PR driver/27622

Ian Lance Taylor ian@airs.com
Mon Aug 28 00:16:00 GMT 2006


This patch to the pexecute code fixes PR driver/27622.  That PR was
about a problem in which the assembler dies early, and the compiler
driver hangs forever waiting for cc1 to complete.  This only happens
when using -pipe.

The problem is that cc1 is writing to a pipe, and cc1 also is holding
an open read descriptor on the pipe which it will never use.  When the
assembler dies quickly, it closes its copy of the pipe.  When cc1
writes to the pipe, there is still an open read descriptor in cc1
itself.  So the write to the pipe succeeds, the pipe buffer fills up,
and cc1 blocks.

The fix, of course, is to not let cc1 hold an open read descriptor on
the pipe to which it is writing.  With this patch cc1 will try to
write to a pipe for which there is no open reader and will die with a
SIGPIPE.  The gcc driver will see that and handle it correctly.

Patch tested with bootstrap and testsuite run on i686-pc-linux-gnu,
and committed.

Ian


	PR driver/27622
	* pex-common.h (struct pex_funcs): Add toclose parameter to
	exec_child field.
	* pex-common.c (pex_run_in_environment): Pass toclose to
	exec_child.
	* pex-djgpp.c (pex_djgpp_exec_child): Add toclose parameter.
	* pex-unix.c (pex_unix_exec_child): Likewise.
	* pex-msdos.c (pex_msdos_exec_child): Likewise.
	* pex-win32.c (pex_win32_exec_child): Likewise.


Index: pex-common.h
===================================================================
--- pex-common.h	(revision 116492)
+++ pex-common.h	(working copy)
@@ -96,17 +96,20 @@ struct pex_funcs
   int (*open_write) (struct pex_obj *, const char */* name */,
                      int /* binary */);
   /* Execute a child process.  FLAGS, EXECUTABLE, ARGV, ERR are from
-     pex_run.  IN, OUT, ERRDES are each a descriptor, from open_read,
-     open_write, or pipe, or they are one of STDIN_FILE_NO,
-     STDOUT_FILE_NO or STDERR_FILE_NO; if not STD*_FILE_NO, they
-     should be closed.  The function should handle the
+     pex_run.  IN, OUT, ERRDES, TOCLOSE are all descriptors, from
+     open_read, open_write, or pipe, or they are one of STDIN_FILE_NO,
+     STDOUT_FILE_NO or STDERR_FILE_NO; if IN, OUT, and ERRDES are not
+     STD*_FILE_NO, they should be closed.  If the descriptor TOCLOSE
+     is not -1, and the system supports pipes, TOCLOSE should be
+     closed in the child process.  The function should handle the
      PEX_STDERR_TO_STDOUT flag.  Return >= 0 on success, or -1 on
      error and set *ERRMSG and *ERR.  */
   long (*exec_child) (struct pex_obj *, int /* flags */,
                       const char */* executable */, char * const * /* argv */,
                       char * const * /* env */,
                       int /* in */, int /* out */, int /* errdes */,
-		      const char **/* errmsg */, int */* err */);
+		      int /* toclose */, const char **/* errmsg */,
+		      int */* err */);
   /* Close a descriptor.  Return 0 on success, -1 on error.  */
   int (*close) (struct pex_obj *, int);
   /* Wait for a child to complete, returning exit status in *STATUS
Index: pex-common.c
===================================================================
--- pex-common.c	(revision 116492)
+++ pex-common.c	(working copy)
@@ -157,6 +157,7 @@ pex_run_in_environment (struct pex_obj *
   char *outname;
   int outname_allocated;
   int p[2];
+  int toclose;
   long pid;
 
   in = -1;
@@ -297,10 +298,18 @@ pex_run_in_environment (struct pex_obj *
 	}
     }
 
+  /* If we are using pipes, the child process has to close the next
+     input pipe.  */
+
+  if ((obj->flags & PEX_USE_PIPES) == 0)
+    toclose = -1;
+  else
+    toclose = obj->next_input;
+
   /* Run the program.  */
 
   pid = obj->funcs->exec_child (obj, flags, executable, argv, env,
-                                in, out, errdes, &errmsg, err);
+				in, out, errdes, toclose, &errmsg, err);
   if (pid < 0)
     goto error_exit;
 
Index: pex-djgpp.c
===================================================================
--- pex-djgpp.c	(revision 116492)
+++ pex-djgpp.c	(working copy)
@@ -46,7 +46,7 @@ static int pex_djgpp_open_read (struct p
 static int pex_djgpp_open_write (struct pex_obj *, const char *, int);
 static long pex_djgpp_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
-                                  int, int, int,
+				  int, int, int, int,
 				  const char **, int *);
 static int pex_djgpp_close (struct pex_obj *, int);
 static int pex_djgpp_wait (struct pex_obj *, long, int *, struct pex_time *,
@@ -114,7 +114,8 @@ static long
 pex_djgpp_exec_child (struct pex_obj *obj, int flags, const char *executable,
 		      char * const * argv, char * const * env,
                       int in, int out, int errdes,
-		      const char **errmsg, int *err)
+		      int toclose ATTRIBUTE_UNUSED, const char **errmsg,
+		      int *err)
 {
   int org_in, org_out, org_errdes;
   int status;
Index: pex-unix.c
===================================================================
--- pex-unix.c	(revision 116492)
+++ pex-unix.c	(working copy)
@@ -271,7 +271,8 @@ static int pex_unix_open_read (struct pe
 static int pex_unix_open_write (struct pex_obj *, const char *, int);
 static long pex_unix_exec_child (struct pex_obj *, int, const char *,
 				 char * const *, char * const *,
-                                 int, int, int, const char **, int *);
+				 int, int, int, int,
+				 const char **, int *);
 static int pex_unix_close (struct pex_obj *, int);
 static int pex_unix_wait (struct pex_obj *, long, int *, struct pex_time *,
 			  int, const char **, int *);
@@ -358,7 +359,7 @@ static long
 pex_unix_exec_child (struct pex_obj *obj, int flags, const char *executable,
 		     char * const * argv, char * const * env,
                      int in, int out, int errdes,
-		     const char **errmsg, int *err)
+		     int toclose, const char **errmsg, int *err)
 {
   pid_t pid;
 
@@ -408,6 +409,11 @@ pex_unix_exec_child (struct pex_obj *obj
 	  if (close (errdes) < 0)
 	    pex_child_error (obj, executable, "close", errno);
 	}
+      if (toclose >= 0)
+	{
+	  if (close (toclose) < 0)
+	    pex_child_error (obj, executable, "close", errno);
+	}
       if ((flags & PEX_STDERR_TO_STDOUT) != 0)
 	{
 	  if (dup2 (STDOUT_FILE_NO, STDERR_FILE_NO) < 0)
Index: pex-msdos.c
===================================================================
--- pex-msdos.c	(revision 116492)
+++ pex-msdos.c	(working copy)
@@ -56,7 +56,8 @@ static int pex_msdos_open (struct pex_ob
 static int pex_msdos_fdindex (struct pex_msdos *, int);
 static long pex_msdos_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
-                                  int, int, int, const char **, int *);
+				  int, int, int, int,
+				  int, const char **, int *);
 static int pex_msdos_close (struct pex_obj *, int);
 static int pex_msdos_wait (struct pex_obj *, long, int *, struct pex_time *,
 			   int, const char **, int *);
@@ -154,6 +155,7 @@ pex_msdos_close (struct pex_obj *obj, in
 static long
 pex_msdos_exec_child (struct pex_obj *obj, int flags, const char *executable,
 		      char * const * argv, char * const * env, int in, int out,
+		      int toclose ATTRIBUTE_UNUSED,
 		      int errdes ATTRIBUTE_UNUSED, const char **errmsg,
 		      int *err)
 {
Index: pex-win32.c
===================================================================
--- pex-win32.c	(revision 116492)
+++ pex-win32.c	(working copy)
@@ -81,7 +81,7 @@ static int pex_win32_open_read (struct p
 static int pex_win32_open_write (struct pex_obj *, const char *, int);
 static long pex_win32_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
-                                  int, int, int,
+                                  int, int, int, int,
 				  const char **, int *);
 static int pex_win32_close (struct pex_obj *, int);
 static int pex_win32_wait (struct pex_obj *, long, int *,
@@ -699,7 +699,9 @@ static long
 pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
 		      const char *executable, char * const * argv,
                       char* const* env,
-		      int in, int out, int errdes, const char **errmsg,
+		      int in, int out, int errdes,
+		      int toclose ATTRIBUTE_UNUSED,
+		      const char **errmsg,
 		      int *err)
 {
   long pid;



More information about the Gcc-patches mailing list