diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-07-21 18:27:35 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-07-21 18:27:35 +0000 |
commit | df206c6e77551b7eebfa1b7995b2556ac369f4fd (patch) | |
tree | ac8824d9cde261316f55212382c6ca9eb2255bd7 /libgo/runtime/go-caller.c | |
parent | 2401ffc3fe5f79e7a1087d8f98f5e3b8bbb1e379 (diff) | |
download | gcc-df206c6e77551b7eebfa1b7995b2556ac369f4fd.zip gcc-df206c6e77551b7eebfa1b7995b2556ac369f4fd.tar.gz gcc-df206c6e77551b7eebfa1b7995b2556ac369f4fd.tar.bz2 |
runtime: don't use runtime_lock in __go_get_backtrace_state
If getSiginfo does not know how to determine the PC, it will call
runtime_callers. That can happen in a thread that was started by
non-Go code, in which case the TLS variable g will not be set, in
which case runtime_lock will crash.
Avoid the problem by using atomic operations for the lock. This is OK
since creating a backtrace state is fast and never blocks.
The test case is TestCgoExternalThreadSIGPROF in the runtime package
on a system that getSiginfo doesn't handle specially.
Updates golang/go#20931
Reviewed-on: https://go-review.googlesource.com/50650
From-SVN: r250439
Diffstat (limited to 'libgo/runtime/go-caller.c')
-rw-r--r-- | libgo/runtime/go-caller.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/libgo/runtime/go-caller.c b/libgo/runtime/go-caller.c index a35d8d7..360bae6 100644 --- a/libgo/runtime/go-caller.c +++ b/libgo/runtime/go-caller.c @@ -74,7 +74,7 @@ static void *back_state; /* A lock to control creating back_state. */ -static Lock back_state_lock; +static uint32 back_state_lock; /* The program arguments. */ @@ -85,7 +85,15 @@ extern Slice runtime_get_args(void); struct backtrace_state * __go_get_backtrace_state () { - runtime_lock (&back_state_lock); + uint32 set; + + /* We may not have a g here, so we can't use runtime_lock. */ + set = 0; + while (!__atomic_compare_exchange_n (&back_state_lock, &set, 1, false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) + { + runtime_osyield (); + set = 0; + } if (back_state == NULL) { Slice args; @@ -113,7 +121,7 @@ __go_get_backtrace_state () back_state = backtrace_create_state (filename, 1, error_callback, NULL); } - runtime_unlock (&back_state_lock); + __atomic_store_n (&back_state_lock, 0, __ATOMIC_RELEASE); return back_state; } |