diff options
Diffstat (limited to 'libgfortran/runtime/backtrace.c')
-rw-r--r-- | libgfortran/runtime/backtrace.c | 19 |
1 files changed, 14 insertions, 5 deletions
diff --git a/libgfortran/runtime/backtrace.c b/libgfortran/runtime/backtrace.c index 77dd4d5f0ac..d7e72c80460 100644 --- a/libgfortran/runtime/backtrace.c +++ b/libgfortran/runtime/backtrace.c @@ -135,14 +135,23 @@ full_callback (void *data, uintptr_t pc, const char *filename, void show_backtrace (bool in_signal_handler) { + /* 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_saved; 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 == NULL) - return; + lbstate = __atomic_load_n (&lbstate_saved, __ATOMIC_RELAXED); + if (!lbstate) + { + lbstate = backtrace_create_state (NULL, __gthread_active_p (), + error_callback, NULL); + if (lbstate) + __atomic_store_n (&lbstate_saved, lbstate, __ATOMIC_RELAXED); + else + return; + } if (!BACKTRACE_SUPPORTED || (in_signal_handler && BACKTRACE_USES_MALLOC)) { |