+2011-05-14 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.
+
2011-05-14 Janne Blomqvist <jb@gcc.gnu.org>
* gfortran.texi: Remove GFORTRAN_USE_STDERR documentation.
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;
* 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
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
@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
@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}.
@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,
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
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;
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;
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));
+2011-05-14 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, update filter symbol name
+ due to backtrace_handler renaming.
+ * 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.
+
2011-05-14 Janne Blomqvist <jb@gcc.gnu.org>
* io/unix.c (st_vprintf,st_printf): Move to runtime/error.c.
void PREFIX(abort) (void)
{
- close_units ();
- abort ();
+ sys_abort ();
}
const char *separator;
int 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. */
int allow_std;
int pedantic;
int convert;
- int dump_core;
int backtrace;
int sign_zero;
size_t record_marker;
#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 ssize_t estr_write (const char *);
internal_proto(estr_write);
if (strncasecmp (func, "*_gfortran", 10) == 0
|| strncasecmp (func, "_gfortran", 9) == 0
|| strcmp (func, "main") == 0 || strcmp (func, "_start") == 0
- || strcmp (func, "_gfortrani_handler") == 0)
+ || strcmp (func, "_gfortrani_backtrace_handler") == 0)
continue;
if (local_strcasestr (str[i], "libgfortran.so") != NULL
/* Fallback to the glibc backtrace. */
estr_write ("\nBacktrace for this error:\n");
dump_glibc_backtrace (depth, str);
+ return;
#endif
+ estr_write ("\nBacktrace not yet available on this platform, sorry!\n");
}
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);
}
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)
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
| 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;
{"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},
estr_write ("\nCommand line arguments:\n");
estr_write (" --help Print this list\n");
- sys_exit (0);
+ exit (0);
}
/* This is the handling of the GFORTRAN_CONVERT_UNITS environment variable.
#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)
- estr_write ("** 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
- estr_write ("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 then 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
* 1 Terminated because of operating system error.
* 2 Error in the runtime library
* 3 Internal error in runtime library
- * 4 Error during error processing (very bad)
*
* Other error returns are reserved for the STOP statement with a numeric code.
*/
#define ERROR_MESSAGE "Internal error: buffer overrun in st_vprintf()\n"
write (STDERR_FILENO, buffer, ST_VPRINTF_SIZE - 1);
write (STDERR_FILENO, ERROR_MESSAGE, strlen(ERROR_MESSAGE));
- sys_exit(2);
+ sys_abort ();
#undef ERROR_MESSAGE
}
}
+/* 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 *
/* Don't even try to print something at this point */
if (magic == MAGIC)
- sys_exit (4);
+ sys_abort ();
magic = MAGIC;
}
estr_write ("\n");
estr_write (message);
estr_write ("\n");
- sys_exit (1);
+ exit (1);
}
iexport(os_error);
st_vprintf (message, ap);
va_end (ap);
estr_write ("\n");
- sys_exit (2);
+ exit (2);
}
iexport(runtime_error);
st_vprintf (message, ap);
va_end (ap);
estr_write ("\n");
- sys_exit (2);
+ exit (2);
}
iexport(runtime_error_at);
because hopefully it doesn't happen too often). */
stupid_function_name_for_static_linking();
- sys_exit (3);
+ exit (3);
}
estr_write ("Fortran runtime error: ");
estr_write (message);
estr_write ("\n");
- sys_exit (2);
+ exit (2);
}
iexport(generate_error);
estr_write ("Fortran runtime error: ");
estr_write (message);
estr_write ("\n");
- sys_exit (2);
+ exit (2);
}
else
{
else
st_printf ("STOP %d\n", (int)code);
- sys_exit (code);
+ exit (code);
}
stop_numeric_f08 (GFC_INTEGER_4 code)
{
st_printf ("STOP %d\n", (int)code);
- sys_exit (code);
+ exit (code);
}
(void) sizeof (w); /* Avoid compiler warning about not using w. */
estr_write ("\n");
}
- sys_exit (0);
+ exit (0);
}
(void) sizeof (w); /* Avoid compiler warning about not using w. */
estr_write ("\n");
- sys_exit (1);
+ sys_abort ();
}
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);
}