diff mbox

libgo patch committed: don't use runtime_lock in __go_get_backtrace_state

Message ID CAOyqgcX_qcO3y4FKoc=a2FVUrmu=dZd=gcs01Z6k20Cmgp_z9Q@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor July 21, 2017, 6:27 p.m. UTC
If getSiginfo in libgo 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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu and
powerpc64le-unknown-linux-gnu.  Committed to mainline.

Ian
diff mbox

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 250436)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-a9f1aeced86691de891fbf2a8c97e848faf1962e
+b712bacd939466e66972337744983e180849c535
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: libgo/runtime/go-caller.c
===================================================================
--- libgo/runtime/go-caller.c	(revision 250406)
+++ libgo/runtime/go-caller.c	(working copy)
@@ -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;
 }