runtime: prevent deadlock when profiling signal arrives in stack scan
authorIan Lance Taylor <ian@gcc.gnu.org>
Sat, 29 Dec 2018 00:07:06 +0000 (00:07 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Sat, 29 Dec 2018 00:07:06 +0000 (00:07 +0000)
    Precise stack scan needs to unwind the stack. When it is
    unwinding the stack, if a profiling signal arrives, which also
    does a traceback, it may deadlock in dl_iterate_phdr. Prevent
    this deadlock by setting up runtime_in_callers before traceback.

    Reviewed-on: https://go-review.googlesource.com/c/155766

From-SVN: r267457

gcc/go/gofrontend/MERGE
libgo/runtime/go-callers.c
libgo/runtime/go-unwind.c
libgo/runtime/runtime.h

index 2552025d9de3292de41e90f3b33c8b60f8163627..a36396c3910720898d67db42e9a3360799fdf52d 100644 (file)
@@ -1,4 +1,4 @@
-d9a30434440469c640a120fe7132057f5644d38c
+0e482bef69d73b9381dbc543e200a1fe57275e81
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index b16ae0c40368c0a4af914e4e3f7b7beaaad08eae..78ada7a26e9bb0ef0c1b916de14fe218b3213f8d 100644 (file)
@@ -16,7 +16,7 @@
    older versions of glibc when a SIGPROF signal arrives while
    collecting a backtrace.  */
 
-static uint32 runtime_in_callers;
+uint32 __go_runtime_in_callers;
 
 /* Argument passed to callback function.  */
 
@@ -185,7 +185,7 @@ bool alreadyInCallers(void)
 bool
 alreadyInCallers()
 {
-  return runtime_atomicload(&runtime_in_callers) > 0;
+  return runtime_atomicload(&__go_runtime_in_callers) > 0;
 }
 
 /* Gather caller PC's.  */
@@ -203,9 +203,9 @@ runtime_callers (int32 skip, Location *locbuf, int32 m, bool keep_thunks)
   data.max = m;
   data.keep_thunks = keep_thunks;
   state = __go_get_backtrace_state ();
-  runtime_xadd (&runtime_in_callers, 1);
+  runtime_xadd (&__go_runtime_in_callers, 1);
   backtrace_full (state, 0, callback, error_callback, &data);
-  runtime_xadd (&runtime_in_callers, -1);
+  runtime_xadd (&__go_runtime_in_callers, -1);
 
   /* For some reason GCC sometimes loses the name of a thunk function
      at the top of the stack.  If we are skipping thunks, skip that
index 58cb27084a88756ee79dc48aae23b70ab467f507..158cbd07968efa01d6504b1c2fa96226421dba23 100644 (file)
@@ -792,7 +792,9 @@ bool
 scanstackwithmap (void *gcw)
 {
   _Unwind_Reason_Code code;
+  runtime_xadd (&__go_runtime_in_callers, 1);
   code = _Unwind_Backtrace (scanstackwithmap_callback, gcw);
+  runtime_xadd (&__go_runtime_in_callers, -1);
   return code == _URC_END_OF_STACK;
 }
 
index 21921ec16dfbe276445620285ba35e3178f1e253..9f6e251b1cd504c49302fc43b0023176a2d563aa 100644 (file)
@@ -515,3 +515,9 @@ bool runtime_usestackmaps;
 
 bool probestackmaps(void)
   __asm__("runtime.probestackmaps");
+
+// 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.
+extern uint32 __go_runtime_in_callers;