libgo: Avoid some cases of getting callers recursively.

Avoids hanging inside older versions of glibc that do not
support recurive calls to dl_iterate_phdr.

From-SVN: r205561
This commit is contained in:
Ian Lance Taylor 2013-12-01 01:40:16 +00:00
parent 2d7930e5e3
commit 2583109c81
3 changed files with 19 additions and 0 deletions

View file

@ -11,6 +11,13 @@
#include "runtime.h"
#include "array.h"
/* This is set to non-zero when calling backtrace_full. This is used
to avoid getting hanging on a recursive lock in dl_iterate_phdr on
older versions of glibc when a SIGPROF signal arrives while
collecting a backtrace. */
uint32 runtime_in_callers;
/* Argument passed to callback function. */
struct callers_data
@ -111,8 +118,10 @@ runtime_callers (int32 skip, Location *locbuf, int32 m)
data.skip = skip + 1;
data.index = 0;
data.max = m;
runtime_xadd (&runtime_in_callers, 1);
backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback,
&data);
runtime_xadd (&runtime_in_callers, -1);
return data.index;
}

View file

@ -2454,6 +2454,15 @@ runtime_sigprof()
return;
}
n = 0;
if(runtime_atomicload(&runtime_in_callers) > 0) {
// If SIGPROF arrived while already fetching runtime
// callers we can have trouble on older systems
// because the unwind library calls dl_iterate_phdr
// which was not recursive in the past.
traceback = false;
}
if(traceback) {
n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf));
for(i = 0; i < n; i++)

View file

@ -776,6 +776,7 @@ extern struct backtrace_state *__go_get_backtrace_state(void);
extern _Bool __go_file_line(uintptr, String*, String*, intgo *);
extern byte* runtime_progname();
extern void runtime_main(void*);
extern uint32 runtime_in_callers;
int32 getproccount(void);