Initialize backtrace state once
authorJanne Blomqvist <jb@gcc.gnu.org>
Fri, 30 Nov 2018 16:44:27 +0000 (18:44 +0200)
committerJanne Blomqvist <jb@gcc.gnu.org>
Fri, 30 Nov 2018 16:44:27 +0000 (18:44 +0200)
From backtrace.h for backtrace_create_state:

   Calling this function allocates resources that can not be freed.
   There is no backtrace_free_state function.  The state is used to
   cache information that is expensive to recompute.  Programs are
   expected to call this function at most once and to save the return
   value for all later calls to backtrace functions.

So instead of calling backtrace_create_state every time we wish to
show a backtrace, do it once and store the result in a static
variable.  libbacktrace allows multiple threads to access the state,
so no need to use TLS.

Regtested on x86_64-pc-linux-gnu.

libgfortran/ChangeLog:

2018-11-30  Janne Blomqvist  <jb@gcc.gnu.org>

PR libfortran/88137
* runtime/backtrace.c (show_backtrace): Make lbstate a static
variable, initialize once.

From-SVN: r266677

libgfortran/ChangeLog
libgfortran/runtime/backtrace.c

index d9397623ee1a4dd3c1d1c74ecd0f482b19c2d262..f1f7cbe4effee5e164b744b3f3d92d0932ffb35a 100644 (file)
@@ -1,3 +1,9 @@
+2018-11-30  Janne Blomqvist  <jb@gcc.gnu.org>
+
+       PR libfortran/88137
+       * runtime/backtrace.c (show_backtrace): Make lbstate a static
+       variable, initialize once.
+
 2018-11-23  Janne Blomqvist  <jb@gcc.gnu.org>
 
        * runtime/error.c (MAGIC): Remove.
index e0c277044b62058184350553ae8dacb9b55b05cd..3fc973a5e6daf7cfa42b836d1213ca13cb915ee2 100644 (file)
@@ -146,11 +146,15 @@ full_callback (void *data, uintptr_t pc, const char *filename,
 void
 show_backtrace (bool in_signal_handler)
 {
-  struct backtrace_state *lbstate;
+  /* Note that libbacktrace allows the state to be accessed from
+     multiple threads, so we don't need to use a TLS variable for the
+     state here.  */
+  static struct backtrace_state *lbstate;
   struct mystate state = { 0, false, in_signal_handler };
-  lbstate = backtrace_create_state (NULL, __gthread_active_p (),
-                                   error_callback, NULL);
+
+  if (!lbstate)
+    lbstate = backtrace_create_state (NULL, __gthread_active_p (),
+                                     error_callback, NULL);
 
   if (lbstate == NULL)
     return;