|
1 From 2a6c7739b5bdb5fbaf743d89a18bd466fb178fe1 Mon Sep 17 00:00:00 2001 |
|
2 From: Austin Clements <[email protected]> |
|
3 Date: Wed, 18 Nov 2015 13:20:35 -0500 |
|
4 Subject: [PATCH 46/63] [release-branch.go1.5] runtime: handle sigprof in |
|
5 stackBarrier |
|
6 |
|
7 Currently, if a profiling signal happens in the middle of |
|
8 stackBarrier, gentraceback may see inconsistencies between stkbar and |
|
9 the barriers on the stack and it will certainly get the wrong return |
|
10 PC for stackBarrier. In most cases, the return PC won't be a PC at all |
|
11 and this will immediately abort the traceback (which is considered |
|
12 okay for a sigprof), but if it happens to be a valid PC this may sent |
|
13 gentraceback down a rabbit hole. |
|
14 |
|
15 Fix this by detecting when the gentraceback starts in stackBarrier and |
|
16 simulating the completion of the barrier to get the correct initial |
|
17 frame. |
|
18 |
|
19 Change-Id: Ib11f705ac9194925f63fe5dfbfc84013a38333e6 |
|
20 Reviewed-on: https://go-review.googlesource.com/17035 |
|
21 Reviewed-by: Russ Cox <[email protected]> |
|
22 Run-TryBot: Austin Clements <[email protected]> |
|
23 TryBot-Result: Gobot Gobot <[email protected]> |
|
24 Reviewed-on: https://go-review.googlesource.com/17056 |
|
25 --- |
|
26 src/runtime/traceback.go | 28 ++++++++++++++++++++++++++++ |
|
27 1 file changed, 28 insertions(+) |
|
28 |
|
29 diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go |
|
30 index 2def359..aed6cbd 100644 |
|
31 --- a/src/runtime/traceback.go |
|
32 +++ b/src/runtime/traceback.go |
|
33 @@ -188,6 +188,34 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in |
|
34 } |
|
35 |
|
36 f := findfunc(frame.pc) |
|
37 + if f.entry == stackBarrierPC { |
|
38 + // We got caught in the middle of a stack barrier |
|
39 + // (presumably by a signal), so stkbar may be |
|
40 + // inconsistent with the barriers on the stack. |
|
41 + // Simulate the completion of the barrier. |
|
42 + // |
|
43 + // On x86, SP will be exactly one word above |
|
44 + // savedLRPtr. On LR machines, SP will be above |
|
45 + // savedLRPtr by some frame size. |
|
46 + var stkbarPos uintptr |
|
47 + if len(stkbar) > 0 && stkbar[0].savedLRPtr < sp0 { |
|
48 + // stackBarrier has not incremented stkbarPos. |
|
49 + stkbarPos = gp.stkbarPos |
|
50 + } else if gp.stkbarPos > 0 && gp.stkbar[gp.stkbarPos-1].savedLRPtr < sp0 { |
|
51 + // stackBarrier has incremented stkbarPos. |
|
52 + stkbarPos = gp.stkbarPos - 1 |
|
53 + } else { |
|
54 + printlock() |
|
55 + print("runtime: failed to unwind through stackBarrier at SP ", hex(sp0), " index ", gp.stkbarPos, "; ") |
|
56 + gcPrintStkbars(gp.stkbar) |
|
57 + print("\n") |
|
58 + throw("inconsistent state in stackBarrier") |
|
59 + } |
|
60 + |
|
61 + frame.pc = gp.stkbar[stkbarPos].savedLRVal |
|
62 + stkbar = gp.stkbar[stkbarPos+1:] |
|
63 + f = findfunc(frame.pc) |
|
64 + } |
|
65 if f == nil { |
|
66 if callback != nil { |
|
67 print("runtime: unknown pc ", hex(frame.pc), "\n") |
|
68 -- |
|
69 2.6.1 |
|
70 |