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
Change-Id: I6007c520e40ba2f00feabf404a7cce7df57fbcef
Reviewed-on: https://go-review.googlesource.com/50650
Reviewed-by: Than McIntosh <thanm@google.com>
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 @@
/* A lock to control creating back_state. */
-static Lock back_state_lock;
+static uint32 back_state_lock;
/* The program arguments. */
@@ -85,7 +85,15 @@
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 @@
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;
}