aboutsummaryrefslogtreecommitdiff
path: root/libgfortran
diff options
context:
space:
mode:
authorJanne Blomqvist <jb@gcc.gnu.org>2011-05-29 23:13:52 +0300
committerJanne Blomqvist <jb@gcc.gnu.org>2011-05-29 23:13:52 +0300
commit155732f56dacb4f10aa48db4d952745aed720bc7 (patch)
treecb0da06274fcd0419a2fe0ae1c347faf09af5f70 /libgfortran
parenteb93b31f68a621299de05ce7774d68c948950123 (diff)
downloadgcc-155732f56dacb4f10aa48db4d952745aed720bc7.zip
gcc-155732f56dacb4f10aa48db4d952745aed720bc7.tar.gz
gcc-155732f56dacb4f10aa48db4d952745aed720bc7.tar.bz2
PR 48931 Use async-signal-safe execve instead of execvp
From-SVN: r174415
Diffstat (limited to 'libgfortran')
-rw-r--r--libgfortran/ChangeLog12
-rw-r--r--libgfortran/libgfortran.h3
-rw-r--r--libgfortran/runtime/backtrace.c12
-rw-r--r--libgfortran/runtime/compile_options.c11
-rw-r--r--libgfortran/runtime/main.c39
5 files changed, 75 insertions, 2 deletions
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index f0e3078..9092921 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,5 +1,17 @@
2011-05-29 Janne Blomqvist <jb@gcc.gnu.org>
+ PR libfortran/48931
+ * libgfortran.h (find_addr2line): New prototype.
+ * runtime/backtrace.c (show_backtrace): Use async-signal-safe
+ execve and stored path of addr2line.
+ * runtime/compile_options.c (maybe_find_addr2line): New function.
+ (set_options): Call maybe_find_addr2line if backtracing is enabled.
+ * runtime/main.c (find_addr2line): New function.
+ (init): Call find_addr2line if backtracing is enabled.
+ (cleanup): Free addr2line_path.
+
+2011-05-29 Janne Blomqvist <jb@gcc.gnu.org>
+
PR libfortran/49214
* runtime/backtrace.c (fd_gets): Return NULL if nothing was read.
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index e77ba10..b72b250 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -665,6 +665,9 @@ export_proto(store_exe_path);
extern char * full_exe_path (void);
internal_proto(full_exe_path);
+extern void find_addr2line (void);
+internal_proto(find_addr2line);
+
/* backtrace.c */
extern void show_backtrace (void);
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c
index 943332a..7d6479f 100644
--- a/libgfortran/runtime/backtrace.c
+++ b/libgfortran/runtime/backtrace.c
@@ -104,6 +104,9 @@ fd_gets (char *s, int size, int fd)
}
+extern char *addr2line_path;
+
+
/* show_backtrace displays the backtrace, currently obtained by means of
the glibc backtrace* functions. */
@@ -124,6 +127,9 @@ show_backtrace (void)
#if CAN_PIPE
+ if (addr2line_path == NULL)
+ goto fallback_noerr;
+
/* We attempt to extract file and line information from addr2line. */
do
{
@@ -146,6 +152,7 @@ show_backtrace (void)
/* Child process. */
#define NUM_FIXEDARGS 7
char *arg[NUM_FIXEDARGS];
+ char *newenv[] = { NULL };
close (f[0]);
@@ -160,14 +167,14 @@ show_backtrace (void)
_exit (1);
close (f[1]);
- arg[0] = (char *) "addr2line";
+ arg[0] = addr2line_path;
arg[1] = (char *) "-e";
arg[2] = full_exe_path ();
arg[3] = (char *) "-f";
arg[4] = (char *) "-s";
arg[5] = (char *) "-C";
arg[6] = NULL;
- execvp (arg[0], arg);
+ execve (addr2line_path, arg, newenv);
_exit (1);
#undef NUM_FIXEDARGS
}
@@ -264,6 +271,7 @@ fallback:
#endif /* CAN_PIPE */
+fallback_noerr:
/* Fallback to the glibc backtrace. */
estr_write ("\nBacktrace for this error:\n");
backtrace_symbols_fd (trace, depth, STDERR_FILENO);
diff --git a/libgfortran/runtime/compile_options.c b/libgfortran/runtime/compile_options.c
index dc0da4b..c3e64de 100644
--- a/libgfortran/runtime/compile_options.c
+++ b/libgfortran/runtime/compile_options.c
@@ -58,6 +58,15 @@ backtrace_handler (int signum)
}
+/* Helper function for set_options because we need to access the
+ global variable options which is not seen in set_options. */
+static void
+maybe_find_addr2line (void)
+{
+ if (options.backtrace == -1)
+ find_addr2line ();
+}
+
/* Set the usual compile-time options. */
extern void set_options (int , int []);
export_proto(set_options);
@@ -131,6 +140,8 @@ set_options (int num, int options[])
#if defined(SIGXFSZ)
signal (SIGXFSZ, backtrace_handler);
#endif
+
+ maybe_find_addr2line ();
}
#endif
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index 54d9e09..bc8dab4 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -139,6 +139,40 @@ full_exe_path (void)
}
+char *addr2line_path;
+
+/* Find addr2line and store the path. */
+
+void
+find_addr2line (void)
+{
+#ifdef HAVE_ACCESS
+#define A2L_LEN 10
+ char *path = getenv ("PATH");
+ size_t n = strlen (path);
+ char ap[n + 1 + A2L_LEN];
+ size_t ai = 0;
+ for (size_t i = 0; i < n; i++)
+ {
+ if (path[i] != ':')
+ ap[ai++] = path[i];
+ else
+ {
+ ap[ai++] = '/';
+ memcpy (ap + ai, "addr2line", A2L_LEN);
+ if (access (ap, R_OK|X_OK) == 0)
+ {
+ addr2line_path = strdup (ap);
+ return;
+ }
+ else
+ ai = 0;
+ }
+ }
+#endif
+}
+
+
/* Set the saved values of the command line arguments. */
void
@@ -185,6 +219,9 @@ init (void)
/* if (argc > 1 && strcmp(argv[1], "--resume") == 0) resume(); */
#endif
+ if (options.backtrace == 1)
+ find_addr2line ();
+
random_seed_i4 (NULL, NULL, NULL);
}
@@ -198,4 +235,6 @@ cleanup (void)
if (please_free_exe_path_when_done)
free ((char *) exe_path);
+
+ free (addr2line_path);
}