runtime: prevent deadlock when profiling signal arrives during traceback

Traceback routines, e.g. callers and funcentry, may call
    __go_get_backtrace_state. If a profiling signal arrives while we
    are in the critical section of __go_get_backtrace_state, it tries
    to do a traceback, which also calls __go_get_backtrace_state,
    which tries to enter the same critical section and will deadlock.
    Prevent this deadlock by setting up runtime_in_callers before
    calling __go_get_backtrace_state.
    
    Found while investigating golang/go#29448. Will add a test in the
    next CL.
    
    Updates golang/go#29448.
    
    Reviewed-on: https://go-review.googlesource.com/c/156037

From-SVN: r267590
This commit is contained in:
Ian Lance Taylor 2019-01-05 00:40:04 +00:00
parent 869fbd357e
commit f6be1179bb
3 changed files with 10 additions and 3 deletions

View File

@ -1,4 +1,4 @@
0e482bef69d73b9381dbc543e200a1fe57275e81 2ce291eaee427799bfcde256929dab89e0ab61eb
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.

View File

@ -137,7 +137,9 @@ __go_file_line (uintptr pc, int index, String *fn, String *file, intgo *line)
runtime_memclr (&c, sizeof c); runtime_memclr (&c, sizeof c);
c.index = index; c.index = index;
runtime_xadd (&__go_runtime_in_callers, 1);
state = __go_get_backtrace_state (); state = __go_get_backtrace_state ();
runtime_xadd (&__go_runtime_in_callers, -1);
backtrace_pcinfo (state, pc, callback, error_callback, &c); backtrace_pcinfo (state, pc, callback, error_callback, &c);
*fn = c.fn; *fn = c.fn;
*file = c.file; *file = c.file;
@ -169,8 +171,13 @@ syminfo_callback (void *data, uintptr_t pc __attribute__ ((unused)),
static _Bool static _Bool
__go_symbol_value (uintptr pc, uintptr *val) __go_symbol_value (uintptr pc, uintptr *val)
{ {
struct backtrace_state *state;
*val = 0; *val = 0;
backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback, runtime_xadd (&__go_runtime_in_callers, 1);
state = __go_get_backtrace_state ();
runtime_xadd (&__go_runtime_in_callers, -1);
backtrace_syminfo (state, pc, syminfo_callback,
error_callback, val); error_callback, val);
return *val != 0; return *val != 0;
} }

View File

@ -202,8 +202,8 @@ runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks)
data.index = 0; data.index = 0;
data.max = m; data.max = m;
data.keep_thunks = keep_thunks; data.keep_thunks = keep_thunks;
state = __go_get_backtrace_state ();
runtime_xadd (&__go_runtime_in_callers, 1); runtime_xadd (&__go_runtime_in_callers, 1);
state = __go_get_backtrace_state ();
backtrace_full (state, 0, callback, error_callback, &data); backtrace_full (state, 0, callback, error_callback, &data);
runtime_xadd (&__go_runtime_in_callers, -1); runtime_xadd (&__go_runtime_in_callers, -1);