fea7751
2004-01-23  Jakub Jelinek  <jakub@redhat.com>
fea7751
fea7751
	* system.h (ICE_EXIT_CODE): Define.
fea7751
	* gcc.c (execute): Don't free first string early, but at the end
fea7751
	of the function.  Call retry_ice if compiler exited with
fea7751
	ICE_EXIT_CODE.
fea7751
	(retry_ice): New function.
fea7751
	* diagnostic.c (diagnostic_count_diagnostic,
fea7751
	diagnostic_action_after_output, error_recursion): Exit with
fea7751
	ICE_EXIT_CODE instead of FATAL_EXIT_CODE.
fea7751
fea7751
--- gcc/system.h.jj	2004-01-19 17:29:30.000000000 +0100
fea7751
+++ gcc/system.h	2004-01-21 11:53:41.000000000 +0100
fea7751
@@ -153,6 +153,10 @@ extern int errno;
fea7751
 # endif
fea7751
 #endif
fea7751
 
fea7751
+#ifndef ICE_EXIT_CODE
fea7751
+# define ICE_EXIT_CODE 27
fea7751
+#endif
fea7751
+
fea7751
 #ifdef HAVE_UNISTD_H
fea7751
 # include <unistd.h>
fea7751
 #endif
fea7751
--- gcc/gcc.c.jj	2004-01-21 11:45:20.000000000 +0100
fea7751
+++ gcc/gcc.c	2004-01-21 11:56:46.000000000 +0100
fea7751
@@ -346,6 +346,9 @@ static void init_gcc_specs (struct obsta
fea7751
 #if defined(HAVE_TARGET_OBJECT_SUFFIX) || defined(HAVE_TARGET_EXECUTABLE_SUFFIX)
fea7751
 static const char *convert_filename (const char *, int, int);
fea7751
 #endif
fea7751
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
fea7751
+static void retry_ice (const char *prog, const char **argv);
fea7751
+#endif
fea7751
 
fea7751
 static const char *if_exists_spec_function (int, const char **);
fea7751
 static const char *if_exists_else_spec_function (int, const char **);
fea7751
@@ -2841,7 +2844,7 @@ execute (void)
fea7751
 	    }
fea7751
 	}
fea7751
 
fea7751
-      if (string != commands[i].prog)
fea7751
+      if (i && string != commands[i].prog)
fea7751
 	free ((void *) string);
fea7751
     }
fea7751
 
fea7751
@@ -2897,6 +2900,16 @@ See %s for instructions.",
fea7751
 	else if (WIFEXITED (status)
fea7751
 		 && WEXITSTATUS (status) >= MIN_FATAL_STATUS)
fea7751
 	  {
fea7751
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
fea7751
+	    /* For ICEs in cc1, cc1obj, cc1plus see if it is
fea7751
+	       reproducible or not.  */
fea7751
+	    char *p;
fea7751
+	    if (WEXITSTATUS (status) == ICE_EXIT_CODE
fea7751
+		&& i == 0
fea7751
+		&& (p = strrchr (commands[0].argv[0], DIR_SEPARATOR))
fea7751
+		&& ! strncmp (p + 1, "cc1", 3))
fea7751
+	      retry_ice (commands[0].prog, commands[0].argv);
fea7751
+#endif
fea7751
 	    if (WEXITSTATUS (status) > greatest_status)
fea7751
 	      greatest_status = WEXITSTATUS (status);
fea7751
 	    ret_code = -1;
fea7751
@@ -2917,6 +2930,9 @@ See %s for instructions.",
fea7751
 	  }
fea7751
       }
fea7751
 
fea7751
+    if (commands[0].argv[0] != commands[0].prog)
fea7751
+      free ((PTR) commands[0].argv[0]);
fea7751
+
fea7751
     return ret_code;
fea7751
   }
fea7751
 }
fea7751
@@ -5898,6 +5914,224 @@ give_switch (int switchnum, int omit_fir
fea7751
   switches[switchnum].validated = 1;
fea7751
 }
fea7751
 
fea7751
+#if !(defined (__MSDOS__) || defined (OS2) || defined (VMS))
fea7751
+#define RETRY_ICE_ATTEMPTS 2
fea7751
+
fea7751
+static void
fea7751
+retry_ice (const char *prog, const char **argv)
fea7751
+{
fea7751
+  int nargs, out_arg = -1, quiet = 0, attempt;
fea7751
+  int pid, retries, sleep_interval;
fea7751
+  const char **new_argv;
fea7751
+  char *temp_filenames[RETRY_ICE_ATTEMPTS * 2 + 2];
fea7751
+
fea7751
+  if (input_filename == NULL || ! strcmp (input_filename, "-"))
fea7751
+    return;
fea7751
+
fea7751
+  for (nargs = 0; argv[nargs] != NULL; ++nargs)
fea7751
+    /* Only retry compiler ICEs, not preprocessor ones.  */
fea7751
+    if (! strcmp (argv[nargs], "-E"))
fea7751
+      return;
fea7751
+    else if (argv[nargs][0] == '-' && argv[nargs][1] == 'o')
fea7751
+      {
fea7751
+	if (out_arg == -1)
fea7751
+	  out_arg = nargs;
fea7751
+	else
fea7751
+	  return;
fea7751
+      }
fea7751
+    /* If the compiler is going to output any time information,
fea7751
+       it might varry between invocations.  */
fea7751
+    else if (! strcmp (argv[nargs], "-quiet"))
fea7751
+      quiet = 1;
fea7751
+    else if (! strcmp (argv[nargs], "-ftime-report"))
fea7751
+      return;
fea7751
+
fea7751
+  if (out_arg == -1 || !quiet)
fea7751
+    return;
fea7751
+
fea7751
+  memset (temp_filenames, '\0', sizeof (temp_filenames));
fea7751
+  new_argv = alloca ((nargs + 3) * sizeof (const char *));
fea7751
+  memcpy (new_argv, argv, (nargs + 1) * sizeof (const char *));
fea7751
+  new_argv[nargs++] = "-frandom-seed=0";
fea7751
+  new_argv[nargs] = NULL;
fea7751
+  if (new_argv[out_arg][2] == '\0')
fea7751
+    new_argv[out_arg + 1] = "-";
fea7751
+  else
fea7751
+    new_argv[out_arg] = "-o-";
fea7751
+
fea7751
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS + 1; ++attempt)
fea7751
+    {
fea7751
+      int fd = -1;
fea7751
+      int status;
fea7751
+
fea7751
+      temp_filenames[attempt * 2] = make_temp_file (".out");
fea7751
+      temp_filenames[attempt * 2 + 1] = make_temp_file (".err");
fea7751
+
fea7751
+      if (attempt == RETRY_ICE_ATTEMPTS)
fea7751
+        {
fea7751
+	  int i;
fea7751
+	  int fd1, fd2;
fea7751
+	  struct stat st1, st2;
fea7751
+	  size_t n, len;
fea7751
+	  char *buf;
fea7751
+
fea7751
+	  buf = xmalloc (8192);
fea7751
+
fea7751
+	  for (i = 0; i < 2; ++i)
fea7751
+	    {
fea7751
+	      fd1 = open (temp_filenames[i], O_RDONLY);
fea7751
+	      fd2 = open (temp_filenames[2 + i], O_RDONLY);
fea7751
+
fea7751
+	      if (fd1 < 0 || fd2 < 0)
fea7751
+		{
fea7751
+		  i = -1;
fea7751
+		  close (fd1);
fea7751
+		  close (fd2);
fea7751
+		  break;
fea7751
+		}
fea7751
+
fea7751
+	      if (fstat (fd1, &st1) < 0 || fstat (fd2, &st2) < 0)
fea7751
+		{
fea7751
+		  i = -1;
fea7751
+		  close (fd1);
fea7751
+		  close (fd2);
fea7751
+		  break;
fea7751
+		}
fea7751
+
fea7751
+	      if (st1.st_size != st2.st_size)
fea7751
+		{
fea7751
+		  close (fd1);
fea7751
+		  close (fd2);
fea7751
+		  break;
fea7751
+		}
fea7751
+
fea7751
+	      len = 0;
fea7751
+	      for (n = st1.st_size; n; n -= len)
fea7751
+		{
fea7751
+		  len = n;
fea7751
+		  if (len > 4096)
fea7751
+		    len = 4096;
fea7751
+
fea7751
+		  if (read (fd1, buf, len) != (int) len
fea7751
+		      || read (fd2, buf + 4096, len) != (int) len)
fea7751
+		    {
fea7751
+		      i = -1;
fea7751
+		      break;
fea7751
+		    }
fea7751
+
fea7751
+		  if (memcmp (buf, buf + 4096, len) != 0)
fea7751
+		    break;
fea7751
+		}
fea7751
+
fea7751
+	      close (fd1);
fea7751
+	      close (fd2);
fea7751
+
fea7751
+	      if (n)
fea7751
+		break;
fea7751
+	    }
fea7751
+
fea7751
+	  free (buf);
fea7751
+	  if (i == -1)
fea7751
+	    break;
fea7751
+
fea7751
+	  if (i != 2)
fea7751
+	    {
fea7751
+	      notice ("The bug is not reproducible, so it is likely a hardware or OS problem.\n");
fea7751
+	      break;
fea7751
+	    }
fea7751
+
fea7751
+          fd = open (temp_filenames[attempt * 2], O_RDWR);
fea7751
+	  if (fd < 0)
fea7751
+	    break;
fea7751
+	  write (fd, "//", 2);
fea7751
+	  for (i = 0; i < nargs; i++)
fea7751
+	    {
fea7751
+	      write (fd, " ", 1);
fea7751
+	      write (fd, new_argv[i], strlen (new_argv[i]));
fea7751
+	    }
fea7751
+	  write (fd, "\n", 1);
fea7751
+	  new_argv[nargs] = "-E";
fea7751
+	  new_argv[nargs + 1] = NULL;
fea7751
+        }
fea7751
+
fea7751
+      /* Fork a subprocess; wait and retry if it fails.  */
fea7751
+      sleep_interval = 1;
fea7751
+      pid = -1;
fea7751
+      for (retries = 0; retries < 4; retries++)
fea7751
+	{
fea7751
+	  pid = fork ();
fea7751
+	  if (pid >= 0)
fea7751
+	    break;
fea7751
+	  sleep (sleep_interval);
fea7751
+	  sleep_interval *= 2;
fea7751
+	}
fea7751
+
fea7751
+      if (pid < 0)
fea7751
+	break;
fea7751
+      else if (pid == 0)
fea7751
+	{
fea7751
+	  if (attempt != RETRY_ICE_ATTEMPTS)
fea7751
+	    fd = open (temp_filenames[attempt * 2], O_RDWR);
fea7751
+	  if (fd < 0)
fea7751
+	    exit (-1);
fea7751
+	  if (fd != 1)
fea7751
+	    {
fea7751
+	      close (1);
fea7751
+	      dup (fd);
fea7751
+	      close (fd);
fea7751
+	    }
fea7751
+
fea7751
+	  fd = open (temp_filenames[attempt * 2 + 1], O_RDWR);
fea7751
+	  if (fd < 0)
fea7751
+	    exit (-1);
fea7751
+	  if (fd != 2)
fea7751
+	    {
fea7751
+	      close (2);
fea7751
+	      dup (fd);
fea7751
+	      close (fd);
fea7751
+	    }
fea7751
+
fea7751
+	  if (prog == new_argv[0])
fea7751
+	    execvp (prog, (char *const *) new_argv);
fea7751
+	  else
fea7751
+	    execv (new_argv[0], (char *const *) new_argv);
fea7751
+	  exit (-1);
fea7751
+	}
fea7751
+
fea7751
+      if (waitpid (pid, &status, 0) < 0)
fea7751
+	break;
fea7751
+
fea7751
+      if (attempt < RETRY_ICE_ATTEMPTS
fea7751
+	  && (! WIFEXITED (status) || WEXITSTATUS (status) != ICE_EXIT_CODE))
fea7751
+	{
fea7751
+	  notice ("The bug is not reproducible, so it is likely a hardware or OS problem.\n");
fea7751
+	  break;
fea7751
+	}
fea7751
+      else if (attempt == RETRY_ICE_ATTEMPTS)
fea7751
+	{
fea7751
+	  close (fd);
fea7751
+	  if (WIFEXITED (status)
fea7751
+	      && WEXITSTATUS (status) == SUCCESS_EXIT_CODE)
fea7751
+	    {
fea7751
+	      notice ("Preprocessed source stored into %s file, please attach this to your bugreport.\n",
fea7751
+		      temp_filenames[attempt * 2]);
fea7751
+	      /* Make sure it is not deleted.  */
fea7751
+	      free (temp_filenames[attempt * 2]);
fea7751
+	      temp_filenames[attempt * 2] = NULL;
fea7751
+	      break;
fea7751
+	    }
fea7751
+	}
fea7751
+    }
fea7751
+
fea7751
+  for (attempt = 0; attempt < RETRY_ICE_ATTEMPTS * 2 + 2; attempt++)
fea7751
+    if (temp_filenames[attempt])
fea7751
+      {
fea7751
+	unlink (temp_filenames[attempt]);
fea7751
+	free (temp_filenames[attempt]);
fea7751
+      }
fea7751
+}
fea7751
+#endif
fea7751
+
fea7751
 /* Search for a file named NAME trying various prefixes including the
fea7751
    user's -B prefix and some standard ones.
fea7751
    Return the absolute file name found.  If nothing is found, return NAME.  */
fea7751
--- gcc/diagnostic.c.jj	2003-10-01 12:09:21.000000000 +0200
fea7751
+++ gcc/diagnostic.c	2004-01-21 11:54:47.000000000 +0100
fea7751
@@ -237,14 +237,14 @@ diagnostic_action_after_output (diagnost
fea7751
       fnotice (stderr, "Please submit a full bug report,\n"
fea7751
 	       "with preprocessed source if appropriate.\n"
fea7751
 	       "See %s for instructions.\n", bug_report_url);
fea7751
-      exit (FATAL_EXIT_CODE);
fea7751
+      exit (ICE_EXIT_CODE);
fea7751
 
fea7751
     case DK_FATAL:
fea7751
       if (context->abort_on_error)
fea7751
 	real_abort ();
fea7751
 
fea7751
       fnotice (stderr, "compilation terminated.\n");
fea7751
-      exit (FATAL_EXIT_CODE);
fea7751
+      exit (ICE_EXIT_CODE);
fea7751
 
fea7751
     default:
fea7751
       gcc_unreachable ();