aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog11
-rw-r--r--libgfortran/libgfortran.h3
-rw-r--r--libgfortran/runtime/backtrace.c3
-rw-r--r--libgfortran/runtime/compile_options.c76
4 files changed, 92 insertions, 1 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 4e47f28..13c6f28 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,4 +1,15 @@
2007-08-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+ Tobias Burnus <burnus@gcc.gnu.org>
+
+ PR fortran/31189
+ * runtime/backtrace.c (show_backtrace): Skip _gfortrani_handler
+ when displaying backtrace.
+ * runtime/compile_options.c: Include <signal.h>.
+ (handler): New function.
+ (set_options): Set signal handlers for backtrace.
+ * libgfortran.h (handler): Add prototype.
+
+2007-08-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
* intrinsics/string_intrinsics.c (compare_string): Return an int.
* libgfortran.h (compare_string): Likewise.
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index 6013ce6..0671801 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -373,6 +373,9 @@ options_t;
extern options_t options;
internal_proto(options);
+extern void handler (int);
+internal_proto(handler);
+
/* Compile-time options that will influence the library. */
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 684ac00..e969341 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -223,7 +223,8 @@ show_backtrace (void)
/* Try to recognize the internal libgfortran functions. */
if (strncasecmp (func, "*_gfortran", 10) == 0
|| strncasecmp (func, "_gfortran", 9) == 0
- || strcmp (func, "main") == 0 || strcmp (func, "_start") == 0)
+ || strcmp (func, "main") == 0 || strcmp (func, "_start") == 0
+ || strcmp (func, "_gfortrani_handler") == 0)
continue;
if (local_strcasestr (str[i], "libgfortran.so") != NULL
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index a6e2a42..c05b400 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -31,10 +31,61 @@ Boston, MA 02110-1301, USA. */
#include "libgfortran.h"
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
/* Useful compile-time options will be stored in here. */
compile_options_t compile_options;
+
+/* A signal handler to allow us to output a backtrace. */
+void
+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);
+}
+
+
/* Set the usual compile-time options. */
extern void set_options (int , int []);
export_proto(set_options);
@@ -56,6 +107,31 @@ set_options (int num, int options[])
compile_options.sign_zero = options[5];
if (num >= 7)
compile_options.bounds_check = options[6];
+
+ /* If backtrace is required, we set signal handlers on most common
+ signals. */
+#if defined(HAVE_SIGNAL_H) && (defined(SIGSEGV) || defined(SIGBUS) \
+ || defined(SIGILL) || defined(SIGFPE))
+ if (compile_options.backtrace)
+ {
+#if defined(SIGSEGV)
+ signal (SIGSEGV, handler);
+#endif
+
+#if defined(SIGBUS)
+ signal (SIGBUS, handler);
+#endif
+
+#if defined(SIGILL)
+ signal (SIGILL, handler);
+#endif
+
+#if defined(SIGFPE)
+ signal (SIGFPE, handler);
+#endif
+ }
+#endif
+
}