1
0
mirror of https://github.com/golang/go synced 2024-11-05 15:16:11 -07:00

runtime: print a message on bad morestack

If morestack runs on the g0 or gsignal stack, it currently performs
some abort operation that typically produces a signal (e.g., it does
an INT $3 on x86). This is useful if you're running in a debugger, but
if you're not, the runtime tries to trap this signal, which is likely
to send the program into a deeper spiral of collapse and lead to very
confusing diagnostic output.

Help out people trying to debug without a debugger by making morestack
print an informative message before blowing up.

Change-Id: I2814c64509b137bfe20a00091d8551d18c2c4749
Reviewed-on: https://go-review.googlesource.com/31133
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Austin Clements 2016-10-13 10:44:57 -04:00
parent 0ba3c607df
commit 687d9d5d78
9 changed files with 52 additions and 16 deletions

View File

@ -354,13 +354,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
MOVL g_m(BX), BX MOVL g_m(BX), BX
MOVL m_g0(BX), SI MOVL m_g0(BX), SI
CMPL g(CX), SI CMPL g(CX), SI
JNE 2(PC) JNE 3(PC)
CALL runtime·badmorestackg0(SB)
INT $3 INT $3
// Cannot grow signal stack. // Cannot grow signal stack.
MOVL m_gsignal(BX), SI MOVL m_gsignal(BX), SI
CMPL g(CX), SI CMPL g(CX), SI
JNE 2(PC) JNE 3(PC)
CALL runtime·badmorestackgsignal(SB)
INT $3 INT $3
// Called from f. // Called from f.

View File

@ -331,13 +331,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
MOVQ g_m(BX), BX MOVQ g_m(BX), BX
MOVQ m_g0(BX), SI MOVQ m_g0(BX), SI
CMPQ g(CX), SI CMPQ g(CX), SI
JNE 2(PC) JNE 3(PC)
CALL runtime·badmorestackg0(SB)
INT $3 INT $3
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVQ m_gsignal(BX), SI MOVQ m_gsignal(BX), SI
CMPQ g(CX), SI CMPQ g(CX), SI
JNE 2(PC) JNE 3(PC)
CALL runtime·badmorestackgsignal(SB)
INT $3 INT $3
// Called from f. // Called from f.

View File

@ -249,13 +249,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0
// Cannot grow scheduler stack (m->g0). // Cannot grow scheduler stack (m->g0).
MOVL m_g0(BX), SI MOVL m_g0(BX), SI
CMPL g(CX), SI CMPL g(CX), SI
JNE 2(PC) JNE 3(PC)
CALL runtime·badmorestackg0(SB)
MOVL 0, AX MOVL 0, AX
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVL m_gsignal(BX), SI MOVL m_gsignal(BX), SI
CMPL g(CX), SI CMPL g(CX), SI
JNE 2(PC) JNE 3(PC)
CALL runtime·badmorestackgsignal(SB)
MOVL 0, AX MOVL 0, AX
// Called from f. // Called from f.

View File

@ -281,12 +281,16 @@ TEXT runtime·morestack(SB),NOSPLIT,$-4-0
MOVW g_m(g), R8 MOVW g_m(g), R8
MOVW m_g0(R8), R4 MOVW m_g0(R8), R4
CMP g, R4 CMP g, R4
BL.EQ runtime·abort(SB) BNE 3(PC)
BL runtime·badmorestackg0(SB)
B runtime·abort(SB)
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVW m_gsignal(R8), R4 MOVW m_gsignal(R8), R4
CMP g, R4 CMP g, R4
BL.EQ runtime·abort(SB) BNE 3(PC)
BL runtime·badmorestackgsignal(SB)
B runtime·abort(SB)
// Called from f. // Called from f.
// Set g->sched to context in f. // Set g->sched to context in f.

View File

@ -256,13 +256,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
MOVD g_m(g), R8 MOVD g_m(g), R8
MOVD m_g0(R8), R4 MOVD m_g0(R8), R4
CMP g, R4 CMP g, R4
BNE 2(PC) BNE 3(PC)
BL runtime·badmorestackg0(SB)
B runtime·abort(SB) B runtime·abort(SB)
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVD m_gsignal(R8), R4 MOVD m_gsignal(R8), R4
CMP g, R4 CMP g, R4
BNE 2(PC) BNE 3(PC)
BL runtime·badmorestackgsignal(SB)
B runtime·abort(SB) B runtime·abort(SB)
// Called from f. // Called from f.

View File

@ -231,12 +231,14 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0
// Cannot grow scheduler stack (m->g0). // Cannot grow scheduler stack (m->g0).
MOVV g_m(g), R7 MOVV g_m(g), R7
MOVV m_g0(R7), R8 MOVV m_g0(R7), R8
BNE g, R8, 2(PC) BNE g, R8, 3(PC)
JAL runtime·badmorestackg0(SB)
JAL runtime·abort(SB) JAL runtime·abort(SB)
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVV m_gsignal(R7), R8 MOVV m_gsignal(R7), R8
BNE g, R8, 2(PC) BNE g, R8, 3(PC)
JAL runtime·badmorestackgsignal(SB)
JAL runtime·abort(SB) JAL runtime·abort(SB)
// Called from f. // Called from f.

View File

@ -284,13 +284,15 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
MOVD g_m(g), R7 MOVD g_m(g), R7
MOVD m_g0(R7), R8 MOVD m_g0(R7), R8
CMP g, R8 CMP g, R8
BNE 2(PC) BNE 3(PC)
BL runtime·badmorestackg0(SB)
BL runtime·abort(SB) BL runtime·abort(SB)
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVD m_gsignal(R7), R8 MOVD m_gsignal(R7), R8
CMP g, R8 CMP g, R8
BNE 2(PC) BNE 3(PC)
BL runtime·badmorestackgsignal(SB)
BL runtime·abort(SB) BL runtime·abort(SB)
// Called from f. // Called from f.

View File

@ -279,13 +279,15 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0
// Cannot grow scheduler stack (m->g0). // Cannot grow scheduler stack (m->g0).
MOVD g_m(g), R7 MOVD g_m(g), R7
MOVD m_g0(R7), R8 MOVD m_g0(R7), R8
CMPBNE g, R8, 2(PC) CMPBNE g, R8, 3(PC)
BL runtime·badmorestackg0(SB)
BL runtime·abort(SB) BL runtime·abort(SB)
// Cannot grow signal stack (m->gsignal). // Cannot grow signal stack (m->gsignal).
MOVD m_gsignal(R7), R8 MOVD m_gsignal(R7), R8
CMP g, R8 CMP g, R8
BNE 2(PC) BNE 3(PC)
BL runtime·badmorestackgsignal(SB)
BL runtime·abort(SB) BL runtime·abort(SB)
// Called from f. // Called from f.

View File

@ -381,6 +381,24 @@ func badreflectcall() {
panic(plainError("arg size to reflect.call more than 1GB")) panic(plainError("arg size to reflect.call more than 1GB"))
} }
var badmorestackg0Msg = "fatal: morestack on g0\n"
//go:nosplit
//go:nowritebarrierrec
func badmorestackg0() {
sp := stringStructOf(&badmorestackg0Msg)
write(2, sp.str, int32(sp.len))
}
var badmorestackgsignalMsg = "fatal: morestack on gsignal\n"
//go:nosplit
//go:nowritebarrierrec
func badmorestackgsignal() {
sp := stringStructOf(&badmorestackgsignalMsg)
write(2, sp.str, int32(sp.len))
}
func lockedOSThread() bool { func lockedOSThread() bool {
gp := getg() gp := getg()
return gp.lockedm != nil && gp.m.lockedg != nil return gp.lockedm != nil && gp.m.lockedg != nil