|
1 From a8e839bb55bdba131d5c2f72d6bb49130fac55e3 Mon Sep 17 00:00:00 2001 |
|
2 From: Austin Clements <[email protected]> |
|
3 Date: Wed, 11 Nov 2015 15:34:54 -0500 |
|
4 Subject: [PATCH 42/63] [release-branch.go1.5] runtime: make SIGPROF skip |
|
5 stacks that are being copied |
|
6 |
|
7 sigprof tracebacks the stack across systemstack switches to make |
|
8 profile tracebacks more complete. However, it does this even if the |
|
9 user stack is currently being copied, which means it may be in an |
|
10 inconsistent state that will cause the traceback to panic. |
|
11 |
|
12 One specific way this can happen is during stack shrinking. Some |
|
13 goroutine blocks for STW, then enters gchelper, which then assists |
|
14 with root marking. If that root marking happens to pick the original |
|
15 goroutine and its stack needs to be shrunk, it will begin to copy that |
|
16 stack. During this copy, the stack is generally inconsistent and, in |
|
17 particular, the actual locations of the stack barriers and their |
|
18 recorded locations are temporarily out of sync. If a SIGPROF happens |
|
19 during this inconsistency, it will walk the stack all the way back to |
|
20 the blocked goroutine and panic when it fails to unwind the stack |
|
21 barriers. |
|
22 |
|
23 Fix this by disallowing jumping to the user stack during SIGPROF if |
|
24 that user stack is in the process of being copied. |
|
25 |
|
26 Fixes #12932. |
|
27 |
|
28 Change-Id: I9ef694c2c01e3653e292ce22612418dd3daff1b4 |
|
29 Reviewed-on: https://go-review.googlesource.com/16819 |
|
30 Reviewed-by: Daniel Morsing <[email protected]> |
|
31 Run-TryBot: Austin Clements <[email protected]> |
|
32 TryBot-Result: Gobot Gobot <[email protected]> |
|
33 Reviewed-on: https://go-review.googlesource.com/16985 |
|
34 Reviewed-by: Ian Lance Taylor <[email protected]> |
|
35 Reviewed-by: Russ Cox <[email protected]> |
|
36 --- |
|
37 src/runtime/proc1.go | 9 ++++++++- |
|
38 1 file changed, 8 insertions(+), 1 deletion(-) |
|
39 |
|
40 diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go |
|
41 index 09cb775..55f1a24 100644 |
|
42 --- a/src/runtime/proc1.go |
|
43 +++ b/src/runtime/proc1.go |
|
44 @@ -2582,7 +2582,14 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { |
|
45 // This is especially important on windows, since all syscalls are cgo calls. |
|
46 n = gentraceback(mp.curg.syscallpc, mp.curg.syscallsp, 0, mp.curg, 0, &stk[0], len(stk), nil, nil, 0) |
|
47 } else if traceback { |
|
48 - n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, _TraceTrap|_TraceJumpStack) |
|
49 + flags := uint(_TraceTrap | _TraceJumpStack) |
|
50 + if gp.m.curg != nil && readgstatus(gp.m.curg) == _Gcopystack { |
|
51 + // We can traceback the system stack, but |
|
52 + // don't jump to the potentially inconsistent |
|
53 + // user stack. |
|
54 + flags &^= _TraceJumpStack |
|
55 + } |
|
56 + n = gentraceback(pc, sp, lr, gp, 0, &stk[0], len(stk), nil, nil, flags) |
|
57 } |
|
58 if !traceback || n <= 0 { |
|
59 // Normal traceback is impossible or has failed. |
|
60 -- |
|
61 2.6.1 |
|
62 |