public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, libfortran] PR 48915 Fix incorrect return code with -fdump-core, error handling changes
@ 2011-05-07 20:09 Janne Blomqvist
  2011-05-13 10:28 ` Janne Blomqvist
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Janne Blomqvist @ 2011-05-07 20:09 UTC (permalink / raw)
  To: Fortran List, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 3358 bytes --]

Hi,

this simple bug led me to rethink normal and error termination and
thus the patch changes some other related stuff as well. So the
original problem was that when -fdump-core was enabled, STOP with a
numeric stop code made the program terminate with an incorrect return
code, since the core dump generation is done by the program killing
itself.

The real problem is that previously, we were mixing up normal
termination with a non-zero exit status (e.g. file not found) with
aborting the program (e.g. some serious error detected). The attached
patch reworks this so that normal termination (with a zero or non-zero
exit code) is done with exit(), and no backtrace or core dump is
generated in any circumstance. For serious errors, a backtrace and
core dump are generated.

Since OS'es contain widely used ways to control core dump generation
(e.g. ulimit -c), and we no longer "frivolously" try to generate a
core dump just because we're exiting with non-zero status, there is
IMHO no longer any need for a gfortran-specific option; if we hit a
serious error, we call abort() and a core dump is always generated if
the user environment is so configured (and the system supports core
dumps).

Also, since backtraces and core dumps are now only generated for
serious errors (not e.g. file not found). -fbacktrace is enabled by
default.

Regtested on x86_64-unknown-linux-gnu, Ok for trunk?

frontend ChangeLog:

2011-05-07  Janne Blomqvist  <jb@gcc.gnu.org>

	PR libfortran/48915
	* gfortran.h (gfc_option_t): Remove flag_dump_core.
	* gfortran.texi (GFORTRAN_ERROR_DUMPCORE): Remove section.
	(GFORTRAN_ERROR_BACKTRACE): Document that it's enabled by default.
	* intrinsic.texi (ABORT): Remove explanation of -fdump-core.
	* invoke.texi: Remove -fdump-core, document that -fbacktrace is
	enabled by default.
	* lang.opt: Remove -fdump-core.
	* options.c (gfc_init_options): Make backtrace default to enabled,
	remove dump_core.
	(gfc_handle_option): Remove OPT_fdump-core.
	* trans-decl.c: Pass a 0 to preserve ABI.

library ChangeLog:

2011-05-07  Janne Blomqvist  <jb@gcc.gnu.org>

	PR libfortran/48915
	* intrinsics/abort.c (abort): Call sys_abort().
	* io/unix.c (st_vprintf): Call sys_abort().
	* libgfortran.h (options_t): Remove dump_core member.
	(handler): Rename to backtrace_handler.
	(compile_options_t): Remove dump_core member.
	(sys_exit): Remove.
	(sys_abort): New function.
	* runtime/backtrace.c (show_backtrace): Print a message if
	backtrace is not available on target.
	* runtime/compile_options.c (backtrace_handler): New
	implementation based on example in Glibc manual.
	(set_options): Remove dump_core handling, make signal handler
	handle more signals.
	(init_compile_options): Remove dump_core.
	* runtime/environ.c (variable_table[]): Remove
	GFORTRAN_ERROR_DUMPCORE element.
	(show_variables): Update name, call exit().
	* runtime/error.c (sys_exit): Remove.
	(sys_abort): New function.
	(recursion_check): Call sys_abort().
	(os_error): Call exit().
	(runtime_error): Likewise.
	(runtime_error_at): Likewise.
	(internal_error): Likewise.
	(generate_error): Likewise.
	(notify_std): Likewise.
	* runtime/stop.c (stop_numeric): Call exit().
	(stop_numeric_f08): Likewise.
	(stop_string): Likewise.
	(error_stop_string): Call sys_abort().
	(error_stop_numeric): Print backtrace, exit with provided code.


-- 
Janne Blomqvist

[-- Attachment #2: abort.diff --]
[-- Type: text/x-patch, Size: 21579 bytes --]

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 92adf72..3b4967d 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2212,7 +2212,6 @@ typedef struct
   int flag_backslash;
   int flag_backtrace;
   int flag_allow_leading_underscore;
-  int flag_dump_core;
   int flag_external_blas;
   int blas_matmul_limit;
   int flag_cray_pointer;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 1284c3d..9910574 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -588,7 +588,6 @@ Malformed environment variables are silently ignored.
 * GFORTRAN_DEFAULT_RECL:: Default record length for new files
 * GFORTRAN_LIST_SEPARATOR::  Separator for list output
 * GFORTRAN_CONVERT_UNIT::  Set endianness for unformatted I/O
-* GFORTRAN_ERROR_DUMPCORE:: Dump core on run-time errors
 * GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors
 @end menu
 
@@ -754,26 +753,15 @@ environment variable will override the CONVERT specifier in the
 open statement}.  This is to give control over data formats to
 users who do not have the source code of their program available.
 
-@node GFORTRAN_ERROR_DUMPCORE
-@section @env{GFORTRAN_ERROR_DUMPCORE}---Dump core on run-time errors
-
-If the @env{GFORTRAN_ERROR_DUMPCORE} variable is set to
-@samp{y}, @samp{Y} or @samp{1} (only the first letter is relevant)
-then library run-time errors cause core dumps.  To disable the core
-dumps, set the variable to @samp{n}, @samp{N}, @samp{0}.  Default
-is not to core dump unless the @option{-fdump-core} compile option
-was used.
-
 @node GFORTRAN_ERROR_BACKTRACE
 @section @env{GFORTRAN_ERROR_BACKTRACE}---Show backtrace on run-time errors
 
-If the @env{GFORTRAN_ERROR_BACKTRACE} variable is set to
-@samp{y}, @samp{Y} or @samp{1} (only the first letter is relevant)
-then a backtrace is printed when a run-time error occurs.
-To disable the backtracing, set the variable to
-@samp{n}, @samp{N}, @samp{0}.  Default is not to print a backtrace
-unless the @option{-fbacktrace} compile option
-was used.
+If the @env{GFORTRAN_ERROR_BACKTRACE} variable is set to @samp{y},
+@samp{Y} or @samp{1} (only the first letter is relevant) then a
+backtrace is printed when a serious run-time error occurs.  To disable
+the backtracing, set the variable to @samp{n}, @samp{N}, @samp{0}.
+Default is to print a backtrace unless the @option{-fno-backtrace}
+compile option was used.
 
 @c =====================================================================
 @c PART II: LANGUAGE REFERENCE
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index ebffb12..804b31f 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -345,10 +345,7 @@ the applicable standard for each intrinsic procedure is noted.
 @table @asis
 @item @emph{Description}:
 @code{ABORT} causes immediate termination of the program.  On operating
-systems that support a core dump, @code{ABORT} will produce a core dump even if
-the option @option{-fno-dump-core} is in effect, which is suitable for debugging
-purposes.
-@c TODO: Check if this (with -fno-dump-core) is correct.
+systems that support a core dump, @code{ABORT} will produce a core dump.
 
 @item @emph{Standard}:
 GNU extension
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index 9f02239..f68b18c 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -145,7 +145,7 @@ and warnings}.
 @item Debugging Options
 @xref{Debugging Options,,Options for debugging your program or GNU Fortran}.
 @gccoptlist{-fdump-fortran-original  -fdump-fortran-optimized @gol
--ffpe-trap=@var{list}  -fdump-core -fbacktrace -fdump-parse-tree}
+-ffpe-trap=@var{list} -fbacktrace -fdump-parse-tree}
 
 @item Directory Options
 @xref{Directory Options,,Options for directory search}.
@@ -935,22 +935,18 @@ Some of the routines in the Fortran runtime library, like
 @code{ffpe-trap=precision} is used. For this reason, the use of 
 @code{ffpe-trap=precision} is not recommended.
 
-@item -fbacktrace
-@opindex @code{fbacktrace}
+@item -fno-backtrace
+@opindex @code{fno-backtrace}
 @cindex backtrace
 @cindex trace
-Specify that, when a runtime error is encountered or a deadly signal is
-emitted (segmentation fault, illegal instruction, bus error or
-floating-point exception), the Fortran runtime
-library should output a backtrace of the error.  This option
-only has influence for compilation of the Fortran main program.
-
-@item -fdump-core
-@cindex core, dump
-@opindex @code{fdump-core}
-Request that a core-dump file is written to disk when a runtime error
-is encountered on systems that support core dumps. This option is
-only effective for the compilation of the Fortran main program.
+When a serious runtime error is encountered or a deadly signal is
+emitted (segmentation fault, illegal instruction, bus error,
+floating-point exception, and the other POSIX signals that have the
+action @samp{core}), the Fortran runtime library tries to output a
+backtrace of the error. @code{-fno-backtrace} disables the backtrace
+generation. This option only has influence for compilation of the
+Fortran main program.
+
 @end table
 
 @xref{Debugging Options,,Options for Debugging Your Program or GCC,
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index ce944e3..a056c5c 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -366,10 +366,6 @@ fdollar-ok
 Fortran
 Allow dollar signs in entity names
 
-fdump-core
-Fortran
-Dump a core file when a runtime error occurs
-
 fdump-fortran-original
 Fortran
 Display the code tree after parsing
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index c67d109..d4778ba 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -134,9 +134,8 @@ gfc_init_options (unsigned int decoded_options_count,
   gfc_option.flag_automatic = 1;
   gfc_option.flag_backslash = 0;
   gfc_option.flag_module_private = 0;
-  gfc_option.flag_backtrace = 0;
+  gfc_option.flag_backtrace = 1;
   gfc_option.flag_allow_leading_underscore = 0;
-  gfc_option.flag_dump_core = 0;
   gfc_option.flag_external_blas = 0;
   gfc_option.blas_matmul_limit = 30;
   gfc_option.flag_cray_pointer = 0;
@@ -697,10 +696,6 @@ gfc_handle_option (size_t scode, const char *arg, int value,
       gfc_option.rtcheck |= GFC_RTCHECK_ARRAY_TEMPS;
       break;
       
-    case OPT_fdump_core:
-      gfc_option.flag_dump_core = value;
-      break;
-
     case OPT_fcray_pointer:
       gfc_option.flag_cray_pointer = value;
       break;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 77e2a59..f0138b0 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -4636,9 +4636,12 @@ create_main_function (tree fndecl)
                                            gfc_option.allow_std));
     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
                             build_int_cst (integer_type_node, pedantic));
+    /* TODO: This is the old -fdump-core option, which is unused but
+       passed due to ABI compatibility; remove when bumping the
+       library ABI.  */
     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
                             build_int_cst (integer_type_node,
-                                           gfc_option.flag_dump_core));
+                                           0));
     CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
                             build_int_cst (integer_type_node,
                                            gfc_option.flag_backtrace));
diff --git a/libgfortran/intrinsics/abort.c b/libgfortran/intrinsics/abort.c
index ada4061..543f8fc 100644
--- a/libgfortran/intrinsics/abort.c
+++ b/libgfortran/intrinsics/abort.c
@@ -30,6 +30,5 @@ export_proto_np(PREFIX(abort));
 
 void PREFIX(abort) (void)
 {
-  close_units ();
-  abort ();
+  sys_abort ();
 }
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 4e4bc3b..dd995ee 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -1383,7 +1383,7 @@ st_vprintf (const char *format, va_list ap)
 #define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
       write (fd, buffer, ST_VPRINTF_SIZE-1);
       write (fd, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
-      sys_exit(2);
+      sys_abort();
 #undef ERROR_MESSAGE
 
     }
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 6cccaca..58fe96b 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -509,15 +509,15 @@ typedef struct
   const char *separator;
 
   int use_stderr, all_unbuffered, unbuffered_preconnected, default_recl;
-  int fpe, dump_core, backtrace;
+  int fpe, backtrace;
 }
 options_t;
 
 extern options_t options;
 internal_proto(options);
 
-extern void handler (int);
-internal_proto(handler);
+extern void backtrace_handler (int);
+internal_proto(backtrace_handler);
 
 
 /* Compile-time options that will influence the library.  */
@@ -528,7 +528,6 @@ typedef struct
   int allow_std;
   int pedantic;
   int convert;
-  int dump_core;
   int backtrace;
   int sign_zero;
   size_t record_marker;
@@ -688,8 +687,8 @@ internal_proto(show_backtrace);
 #define GFC_OTOA_BUF_SIZE (GFC_LARGEST_BUF * 3 + 1)
 #define GFC_BTOA_BUF_SIZE (GFC_LARGEST_BUF * 8 + 1)
 
-extern void sys_exit (int) __attribute__ ((noreturn));
-internal_proto(sys_exit);
+extern void sys_abort (void) __attribute__ ((noreturn));
+internal_proto(sys_abort);
 
 extern const char *gfc_xtoa (GFC_UINTEGER_LARGEST, char *, size_t);
 internal_proto(gfc_xtoa);
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 5e4f15c..2a481cd 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -318,5 +318,7 @@ fallback:
   /* Fallback to the glibc backtrace.  */
   st_printf ("\nBacktrace for this error:\n");
   dump_glibc_backtrace (depth, str);
+  return;
 #endif
+  st_printf ("\nBacktrace not yet available on this platform, sorry!\n");
 }
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index 62c401b..dc0da4b 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -33,49 +33,28 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 compile_options_t compile_options;
 
 
+volatile sig_atomic_t fatal_error_in_progress = 0;
+
 /* A signal handler to allow us to output a backtrace.  */
 void
-handler (int signum)
+backtrace_handler (int signum)
 {
-  const char * name = NULL, * desc = NULL;
-
-  switch (signum)
-    {
-#if defined(SIGSEGV)
-      case SIGSEGV:
-	name = "SIGSEGV";
-	desc = "Segmentation fault";
-	break;
-#endif
-
-#if defined(SIGBUS)
-      case SIGBUS:
-	name = "SIGBUS";
-	desc = "Bus error";
-	break;
-#endif
-
-#if defined(SIGILL)
-      case SIGILL:
-	name = "SIGILL";
-	desc = "Illegal instruction";
-	break;
-#endif
-
-#if defined(SIGFPE)
-      case SIGFPE:
-	name = "SIGFPE";
-	desc = "Floating-point exception";
-	break;
-#endif
-    }
-
-  if (name)
-    st_printf ("\nProgram received signal %d (%s): %s.\n", signum, name, desc);
-  else
-    st_printf ("\nProgram received signal %d.\n", signum);
-
-  sys_exit (5);
+  /* Since this handler is established for more than one kind of signal, 
+     it might still get invoked recursively by delivery of some other kind
+     of signal.  Use a static variable to keep track of that. */
+  if (fatal_error_in_progress)
+    raise (signum);
+  fatal_error_in_progress = 1;
+
+  show_backtrace();
+
+  /* Now reraise the signal.  We reactivate the signal's
+     default handling, which is to terminate the process.
+     We could just call exit or abort,
+     but reraising the signal sets the return status
+     from the process correctly. */
+  signal (signum, SIG_DFL);
+  raise (signum);
 }
 
 
@@ -92,8 +71,9 @@ set_options (int num, int options[])
     compile_options.allow_std = options[1];
   if (num >= 3)
     compile_options.pedantic = options[2];
-  if (num >= 4)
-    compile_options.dump_core = options[3];
+  /* options[3] is the removed -fdump-core option. It's place in the
+     options array is retained due to ABI compatibility. Remove when
+     bumping the library ABI.  */
   if (num >= 5)
     compile_options.backtrace = options[4];
   if (num >= 6)
@@ -103,26 +83,53 @@ set_options (int num, int options[])
   if (num >= 8)
     compile_options.range_check = options[7];
 
-  /* If backtrace is required, we set signal handlers on most common
-     signals.  */
-#if defined(HAVE_SIGNAL) && (defined(SIGSEGV) || defined(SIGBUS) \
-			     || defined(SIGILL) || defined(SIGFPE))
+  /* If backtrace is required, we set signal handlers on the POSIX
+     2001 signals with core action.  */
+#if defined(HAVE_SIGNAL) && (defined(SIGQUIT) || defined(SIGILL) \
+			     || defined(SIGABRT) || defined(SIGFPE) \
+			     || defined(SIGSEGV) || defined(SIGBUS) \
+			     || defined(SIGSYS) || defined(SIGTRAP) \
+			     || defined(SIGXCPU) || defined(SIGXFSZ))
   if (compile_options.backtrace)
     {
+#if defined(SIGQUIT)
+      signal (SIGQUIT, backtrace_handler);
+#endif
+
+#if defined(SIGILL)
+      signal (SIGILL, backtrace_handler);
+#endif
+
+#if defined(SIGABRT)
+      signal (SIGABRT, backtrace_handler);
+#endif
+
+#if defined(SIGFPE)
+      signal (SIGFPE, backtrace_handler);
+#endif
+
 #if defined(SIGSEGV)
-      signal (SIGSEGV, handler);
+      signal (SIGSEGV, backtrace_handler);
 #endif
 
 #if defined(SIGBUS)
-      signal (SIGBUS, handler);
+      signal (SIGBUS, backtrace_handler);
 #endif
 
-#if defined(SIGILL)
-      signal (SIGILL, handler);
+#if defined(SIGSYS)
+      signal (SIGSYS, backtrace_handler);
 #endif
 
-#if defined(SIGFPE)
-      signal (SIGFPE, handler);
+#if defined(SIGTRAP)
+      signal (SIGTRAP, backtrace_handler);
+#endif
+
+#if defined(SIGXCPU)
+      signal (SIGXCPU, backtrace_handler);
+#endif
+
+#if defined(SIGXFSZ)
+      signal (SIGXFSZ, backtrace_handler);
 #endif
     }
 #endif
@@ -140,7 +147,6 @@ init_compile_options (void)
     | GFC_STD_F2003 | GFC_STD_F2008 | GFC_STD_F95 | GFC_STD_F77
     | GFC_STD_F2008_OBS | GFC_STD_GNU | GFC_STD_LEGACY;
   compile_options.pedantic = 0;
-  compile_options.dump_core = 0;
   compile_options.backtrace = 0;
   compile_options.sign_zero = 1;
   compile_options.range_check = 1;
diff --git a/libgfortran/runtime/environ.c b/libgfortran/runtime/environ.c
index a6ce645..502da8f 100644
--- a/libgfortran/runtime/environ.c
+++ b/libgfortran/runtime/environ.c
@@ -319,11 +319,6 @@ static variable variable_table[] = {
   {"GFORTRAN_CONVERT_UNIT", 0, 0, init_unformatted, show_string,
    "Set format for unformatted files", 0},
 
-  /* Behaviour when encoutering a runtime error.  */
-  {"GFORTRAN_ERROR_DUMPCORE", -1, &options.dump_core,
-    init_boolean, show_boolean,
-    "Dump a core file (if possible) on runtime error", -1},
-
   {"GFORTRAN_ERROR_BACKTRACE", -1, &options.backtrace,
     init_boolean, show_boolean,
     "Print out a backtrace (if possible) on runtime error", -1},
@@ -352,7 +347,7 @@ show_variables (void)
   int n;
 
   /* TODO: print version number.  */
-  st_printf ("GNU Fortran 95 runtime library version "
+  st_printf ("GNU Fortran runtime library version "
 	     "UNKNOWN" "\n\n");
 
   st_printf ("Environment variables:\n");
@@ -390,7 +385,7 @@ show_variables (void)
 
   /* st_printf("  --resume <dropfile>  Resume program execution from dropfile\n"); */
 
-  sys_exit (0);
+  exit (0);
 }
 
 /* This is the handling of the GFORTRAN_CONVERT_UNITS environment variable.
diff --git a/libgfortran/runtime/error.c b/libgfortran/runtime/error.c
index 06c144a..9ad435c 100644
--- a/libgfortran/runtime/error.c
+++ b/libgfortran/runtime/error.c
@@ -58,44 +58,32 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #endif
 
 
-/* sys_exit()-- Terminate the program with an exit code.  */
-
-void
-sys_exit (int code)
-{
-  /* Show error backtrace if possible.  */
-  if (code != 0 && code != 4
-      && (options.backtrace == 1
-	  || (options.backtrace == -1 && compile_options.backtrace == 1)))
-    show_backtrace ();
-
-  /* Dump core if requested.  */
-  if (code != 0
-      && (options.dump_core == 1
-	 || (options.dump_core == -1 && compile_options.dump_core == 1)))
-    {
-#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_CORE)
-      /* Warn if a core file cannot be produced because
-	 of core size limit.  */
-
-      struct rlimit core_limit;
-
-      if (getrlimit (RLIMIT_CORE, &core_limit) == 0 && core_limit.rlim_cur == 0)
-	st_printf ("** Warning: a core dump was requested, but the core size"
-		   "limit\n**          is currently zero.\n\n");
-#endif
-      
-      
-#if defined(HAVE_KILL) && defined(HAVE_GETPID) && defined(SIGQUIT)
-      kill (getpid (), SIGQUIT);
-#else
-      st_printf ("Core dump not possible, sorry.");
-#endif
-    }
-
-  exit (code);
-}
-
+/* Termination of a program: F2008 2.3.5 talks about "normal
+   termination" and "error termination". Normal termination occurs as
+   a result of e.g. executing the end program statement, and executing
+   the STOP statement. It includes the effect of the C exit()
+   function. 
+
+   Error termination is initiated when the ERROR STOP statement is
+   executed, when ALLOCATE/DEALLOCATE fails without STAT= being
+   specified, when some of the co-array synchronization statements
+   fail without STAT= being specified, and some I/O errors if
+   ERR/IOSTAT/END/EOR is not present, and finally EXECUTE_COMMAND_LINE
+   failure without CMDSTAT=.
+
+   2.3.5 also explains how co-images synchronize during termination.
+
+   In libgfortran we have two ways of ending a program. exit(code) is
+   a normal exit; calling exit() also causes open units to be
+   closed. No backtrace or core dump is needed here. When something
+   goes wrong, we have sys_abort() which tries to print the backtrace
+   if -fbacktrace is enabled, and the dumps core; whether a core file
+   is generated is system dependent. When aborting, we don't flush and
+   close open units, as program memory might be corrupted and we'd
+   rather risk losing dirty data in the buffers rather than corrupting
+   files on disk.
+
+*/
 
 /* Error conditions.  The tricky part here is printing a message when
  * it is the I/O subsystem that is severely wounded.  Our goal is to
@@ -112,6 +100,28 @@ sys_exit (int code)
  * Other error returns are reserved for the STOP statement with a numeric code.
  */
 
+
+/* sys_abort()-- Terminate the program showing backtrace and dumping
+   core.  */
+
+void
+sys_abort ()
+{
+  /* If backtracing is enabled, print backtrace and disable signal
+     handler for ABRT.  */
+  if (options.backtrace == 1
+      || (options.backtrace == -1 && compile_options.backtrace == 1))
+    {
+      show_backtrace ();
+#if defined(HAVE_SIGNAL) && defined(SIGABRT)
+      signal (SIGABRT, SIG_DFL);
+#endif
+    }
+
+  abort();
+}
+
+
 /* gfc_xtoa()-- Integer to hexadecimal conversion.  */
 
 const char *
@@ -216,7 +226,7 @@ recursion_check (void)
 
   /* Don't even try to print something at this point */
   if (magic == MAGIC)
-    sys_exit (4);
+    sys_abort ();
 
   magic = MAGIC;
 }
@@ -235,7 +245,7 @@ os_error (const char *message)
   recursion_check ();
   st_printf ("Operating system error: %s\n%s\n", 
 	     gf_strerror (errno, errmsg, STRERR_MAXSZ), message);
-  sys_exit (1);
+  exit (1);
 }
 iexport(os_error);
 
@@ -254,7 +264,7 @@ runtime_error (const char *message, ...)
   st_vprintf (message, ap);
   va_end (ap);
   st_printf ("\n");
-  sys_exit (2);
+  exit (2);
 }
 iexport(runtime_error);
 
@@ -273,7 +283,7 @@ runtime_error_at (const char *where, const char *message, ...)
   st_vprintf (message, ap);
   va_end (ap);
   st_printf ("\n");
-  sys_exit (2);
+  exit (2);
 }
 iexport(runtime_error_at);
 
@@ -309,7 +319,7 @@ internal_error (st_parameter_common *cmp, const char *message)
      because hopefully it doesn't happen too often).  */
   stupid_function_name_for_static_linking();
 
-  sys_exit (3);
+  exit (3);
 }
 
 
@@ -475,7 +485,7 @@ generate_error (st_parameter_common *cmp, int family, const char *message)
   recursion_check ();
   show_locus (cmp);
   st_printf ("Fortran runtime error: %s\n", message);
-  sys_exit (2);
+  exit (2);
 }
 iexport(generate_error);
 
@@ -533,7 +543,7 @@ notify_std (st_parameter_common *cmp, int std, const char * message)
       recursion_check ();
       show_locus (cmp);
       st_printf ("Fortran runtime error: %s\n", message);
-      sys_exit (2);
+      exit (2);
     }
   else
     {
diff --git a/libgfortran/runtime/stop.c b/libgfortran/runtime/stop.c
index 29f5031..b2f51a1 100644
--- a/libgfortran/runtime/stop.c
+++ b/libgfortran/runtime/stop.c
@@ -40,7 +40,7 @@ stop_numeric (GFC_INTEGER_4 code)
   else
     st_printf ("STOP %d\n", (int)code);
 
-  sys_exit (code);
+  exit (code);
 }
 
 
@@ -54,7 +54,7 @@ void
 stop_numeric_f08 (GFC_INTEGER_4 code)
 {
   st_printf ("STOP %d\n", (int)code);
-  sys_exit (code);
+  exit (code);
 }
 
 
@@ -70,7 +70,7 @@ stop_string (const char *string, GFC_INTEGER_4 len)
 	st_printf ("%c", *(string++));
       st_printf ("\n");
     }
-  sys_exit (0);
+  exit (0);
 }
 
 
@@ -91,7 +91,7 @@ error_stop_string (const char *string, GFC_INTEGER_4 len)
     st_printf ("%c", *(string++));
   st_printf ("\n");
 
-  sys_exit (1);
+  sys_abort ();
 }
 
 
@@ -105,5 +105,8 @@ void
 error_stop_numeric (GFC_INTEGER_4 code)
 {
   st_printf ("ERROR STOP %d\n", (int) code);
-  sys_exit (code);
+  if (options.backtrace == 1
+      || (options.backtrace == -1 && compile_options.backtrace == 1))
+    show_backtrace ();
+  exit (code);
 }

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2011-05-14 15:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-07 20:09 [Patch, libfortran] PR 48915 Fix incorrect return code with -fdump-core, error handling changes Janne Blomqvist
2011-05-13 10:28 ` Janne Blomqvist
2011-05-14 12:57 ` Steve Kargl
2011-05-14 15:19 ` Tobias Burnus
2011-05-14 18:20   ` Janne Blomqvist
2011-05-14 19:40     ` Tobias Burnus
2011-05-14 19:44       ` Janne Blomqvist

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).