diff mbox

[libfortran] PR 48915 Fix incorrect return code with -fdump-core, error handling changes

Message ID BANLkTi=8wX5VKZRNWsCpd6B1RVtbp5sbaQ@mail.gmail.com
State New
Headers show

Commit Message

Janne Blomqvist May 7, 2011, 7:52 p.m. UTC
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.

Comments

Janne Blomqvist May 13, 2011, 9:22 a.m. UTC | #1
PING.

On Sat, May 7, 2011 at 22:52, Janne Blomqvist <blomqvist.janne@gmail.com> wrote:
> 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
>
Steve Kargl May 14, 2011, 1:06 a.m. UTC | #2
On Sat, May 07, 2011 at 10:52:13PM +0300, Janne Blomqvist wrote:
> 
> 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.
> 

OK.

I suspect that there may be some out given that you're dealing
with signals and gfortran runs on so many different OS's.
Tobias Burnus May 14, 2011, 10:25 a.m. UTC | #3
Janne Blomqvist wrote: PR libfortran/48915
> 	* lang.opt: Remove -fdump-core.

Shouldn't one set this one to "Ignore" instead of removing it? In 
particular as in a way the default option is kind of "-fdump-core"?

> 	* runtime/stop.c (stop_numeric): Call exit().
> 	(error_stop_string): Call sys_abort().
> 	(error_stop_numeric): Print backtrace, exit with provided code.

I disagree with the ERROR STOP change. The useful point about backtraces 
is that one can find out where the program aborted. That's useful when 
signalling NaN occurs, NULL pointers are dereferenced etc.

However, if either the program prints an error (ERROR STOP) or if the 
library prints an error where the file/line number is in the error 
message, it does not make sense to clutter the output by printing a 
backtrace - especially not if the backtracing is enabled by default.

Thus, I do *not* want to see a backtrace for:
- STOP with non-zero exit code
- ERROR STOP
Both: One can easily grep the source code to find the relevant line. 
Additionally, those messages usually print the exact problem - thus 
there is no need to clutter the output.

- Opening an non-existing file
- Out-of-bounds array access
- Deallocating an nonallocated variable
Here, the reason is that the source line is ready printed in the error. 
For instance:
   At line 1 of file test.f90 (unit = 99, file = '�R')
   Fortran runtime error: File 'nonexist' does not exist

Thus, I think one should to change ERROR STOP back to printing no 
backtrace - at least not by default.

(I do not really mind backtraces for deallocation or out-of-bounds 
errors; they occur rare enough and sometimes a backtrace can be useful 
even if the line number is known.)

Additionally, it is *not* sufficient for ERROR STOP to only modify 
libgfortran: For -fcoarray=lib, there is also an ERROR STOP version in 
libgfortran/caf/{single,mpi}.c which should behave analogously - or one 
changes the code there to call libgfortran's ERROR STOP version from there.

Other than that: Nice clean up. One probably should now also implement 
backtracing support for Windows, which is not difficult (cf. attachment 
in the MinGW backtrace PR).

Tobias
Janne Blomqvist May 14, 2011, 3:18 p.m. UTC | #4
On Sat, May 14, 2011 at 13:25, Tobias Burnus <burnus@net-b.de> wrote:
> Janne Blomqvist wrote: PR libfortran/48915
>>
>>        * lang.opt: Remove -fdump-core.
>
> Shouldn't one set this one to "Ignore" instead of removing it?

It suppose one could argue this makes sense, in order to not break
existing makefiles.

> In particular
> as in a way the default option is kind of "-fdump-core"?

Well, I don't know about that. I think -fdump-core was just broken. E.g.

- When enabled, generate a core dump [1] when the library detects any
error such as file not found or EOF and decides to exit with a
non-zero exit status.

- When not enabled, and -fbacktrace not enabled, still generates a
core dump if a fatal signal occurs because that's the default behavior
in POSIX and there's nothing to prevent it [1].

[1] Well, depending on the user configured core file size limit, obviously.

So what the current behavior is, beyond removing the -fdump-core
option, is that it makes gfortran behave more like a good POSIX
citizen, i.e. for most errors we just exit() normally with a non-zero
exit status (no core dump or backtrace attempted). Backtracing and
abort() is reserved for a few situations where we notice something
went very bad.

>>        * runtime/stop.c (stop_numeric): Call exit().
>>        (error_stop_string): Call sys_abort().
>>        (error_stop_numeric): Print backtrace, exit with provided code.
>
> I disagree with the ERROR STOP change.

My thinking is that the spirit of ERROR STOP is that the program
noticed something went seriously wrong (e.g. program state corrupted
in some way), and  hence a backtrace and/or core dump might help
figure out what went wrong. For less serious errors, there's the plain
STOP. Similar to how in C there's exit() and abort().

> Other than that: Nice clean up. One probably should now also implement
> backtracing support for Windows, which is not difficult (cf. attachment in
> the MinGW backtrace PR).

There's also a few problems with the async-signal-safety of the
current backtrace implementation, see PR 48931.
Tobias Burnus May 14, 2011, 3:35 p.m. UTC | #5
Janne Blomqvist wrote:
> >  I disagree with the ERROR STOP change.
> My thinking is that the spirit of ERROR STOP is that the program
> noticed something went seriously wrong (e.g. program state corrupted
> in some way), and  hence a backtrace and/or core dump might help
> figure out what went wrong. For less serious errors, there's the plain
> STOP. Similar to how in C there's exit() and abort().

Well, typical usages would be:
   STOP "Calculation finished"
and
   ERROR STOP "No input file found"

Admittedly, STOP is also used for the latter as there was no ERROR STOP 
until Fortran 2008 - and when using numerical arguments, the value is 
also used as exit status code - with string values, which are rather 
common, STOP has always the success exit status code 0.

Especially with coarrays, one cannot easily prevent the usage of ERROR 
STOP: Assume that this_image() > 1 processes wait for process 1 ("SYNC 
IMAGES(1)") to read in the data and to broadcast it. Now, process 1 sees 
that there is no input file - what shell it do? A STOP would cause a 
dead lock. Thus, one simply calls ERROR STOP "No input file" - and does 
not want to have a backtrace ...

As written, before if one is able to call STOP or ERROR STOP, one knows 
where one is in the program - and at least roughly why one stops there. 
Thus, at least by default, I don't want to have a backtrace. If one had 
a "-fbacktrace=always" or similar, one could still backtrace ERROR STOP 
- and maybe even STOP ;-)

Maybe, we should make the backtrace functionality available like other 
compilers have; looking at our code, I find for Intel
   USE ifcore
   CALL tracebackqq(USER_EXIT_CODE=-1)
and for IBM
   CALL xl__trbk()

Tobias
Janne Blomqvist May 14, 2011, 3:50 p.m. UTC | #6
On Sat, May 14, 2011 at 18:35, Tobias Burnus <burnus@net-b.de> wrote:
> Janne Blomqvist wrote:
>>
>> >  I disagree with the ERROR STOP change.
>> My thinking is that the spirit of ERROR STOP is that the program
>> noticed something went seriously wrong (e.g. program state corrupted
>> in some way), and  hence a backtrace and/or core dump might help
>> figure out what went wrong. For less serious errors, there's the plain
>> STOP. Similar to how in C there's exit() and abort().
>
> Well, typical usages would be:
>  STOP "Calculation finished"
> and
>  ERROR STOP "No input file found"
>
> Admittedly, STOP is also used for the latter as there was no ERROR STOP
> until Fortran 2008 - and when using numerical arguments, the value is also
> used as exit status code - with string values, which are rather common, STOP
> has always the success exit status code 0.
>
> Especially with coarrays, one cannot easily prevent the usage of ERROR STOP:
> Assume that this_image() > 1 processes wait for process 1 ("SYNC IMAGES(1)")
> to read in the data and to broadcast it. Now, process 1 sees that there is
> no input file - what shell it do? A STOP would cause a dead lock. Thus, one
> simply calls ERROR STOP "No input file" - and does not want to have a
> backtrace ...

Good point.

Color me convinced.
diff mbox

Patch

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);
 }