From 687d9d5d78f8a2d09b2052e73be0c83740e17fda Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Thu, 13 Oct 2016 10:44:57 -0400 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Rick Hudson Reviewed-by: Ian Lance Taylor --- src/runtime/asm_386.s | 6 ++++-- src/runtime/asm_amd64.s | 6 ++++-- src/runtime/asm_amd64p32.s | 6 ++++-- src/runtime/asm_arm.s | 8 ++++++-- src/runtime/asm_arm64.s | 6 ++++-- src/runtime/asm_mips64x.s | 6 ++++-- src/runtime/asm_ppc64x.s | 6 ++++-- src/runtime/asm_s390x.s | 6 ++++-- src/runtime/proc.go | 18 ++++++++++++++++++ 9 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s index 56d495aede..4ef738eacb 100644 --- a/src/runtime/asm_386.s +++ b/src/runtime/asm_386.s @@ -354,13 +354,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0 MOVL g_m(BX), BX MOVL m_g0(BX), SI CMPL g(CX), SI - JNE 2(PC) + JNE 3(PC) + CALL runtime·badmorestackg0(SB) INT $3 // Cannot grow signal stack. MOVL m_gsignal(BX), SI CMPL g(CX), SI - JNE 2(PC) + JNE 3(PC) + CALL runtime·badmorestackgsignal(SB) INT $3 // Called from f. diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s index 8d992188de..34da3bda9f 100644 --- a/src/runtime/asm_amd64.s +++ b/src/runtime/asm_amd64.s @@ -331,13 +331,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0 MOVQ g_m(BX), BX MOVQ m_g0(BX), SI CMPQ g(CX), SI - JNE 2(PC) + JNE 3(PC) + CALL runtime·badmorestackg0(SB) INT $3 // Cannot grow signal stack (m->gsignal). MOVQ m_gsignal(BX), SI CMPQ g(CX), SI - JNE 2(PC) + JNE 3(PC) + CALL runtime·badmorestackgsignal(SB) INT $3 // Called from f. diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s index 0b42c666ae..4e3c0cd2b6 100644 --- a/src/runtime/asm_amd64p32.s +++ b/src/runtime/asm_amd64p32.s @@ -249,13 +249,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$0-0 // Cannot grow scheduler stack (m->g0). MOVL m_g0(BX), SI CMPL g(CX), SI - JNE 2(PC) + JNE 3(PC) + CALL runtime·badmorestackg0(SB) MOVL 0, AX // Cannot grow signal stack (m->gsignal). MOVL m_gsignal(BX), SI CMPL g(CX), SI - JNE 2(PC) + JNE 3(PC) + CALL runtime·badmorestackgsignal(SB) MOVL 0, AX // Called from f. diff --git a/src/runtime/asm_arm.s b/src/runtime/asm_arm.s index d768060af2..0c7d580163 100644 --- a/src/runtime/asm_arm.s +++ b/src/runtime/asm_arm.s @@ -281,12 +281,16 @@ TEXT runtime·morestack(SB),NOSPLIT,$-4-0 MOVW g_m(g), R8 MOVW m_g0(R8), 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). MOVW m_gsignal(R8), R4 CMP g, R4 - BL.EQ runtime·abort(SB) + BNE 3(PC) + BL runtime·badmorestackgsignal(SB) + B runtime·abort(SB) // Called from f. // Set g->sched to context in f. diff --git a/src/runtime/asm_arm64.s b/src/runtime/asm_arm64.s index c46569f68c..bd2b18385e 100644 --- a/src/runtime/asm_arm64.s +++ b/src/runtime/asm_arm64.s @@ -256,13 +256,15 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0 MOVD g_m(g), R8 MOVD m_g0(R8), R4 CMP g, R4 - BNE 2(PC) + BNE 3(PC) + BL runtime·badmorestackg0(SB) B runtime·abort(SB) // Cannot grow signal stack (m->gsignal). MOVD m_gsignal(R8), R4 CMP g, R4 - BNE 2(PC) + BNE 3(PC) + BL runtime·badmorestackgsignal(SB) B runtime·abort(SB) // Called from f. diff --git a/src/runtime/asm_mips64x.s b/src/runtime/asm_mips64x.s index 138181833c..e29522367d 100644 --- a/src/runtime/asm_mips64x.s +++ b/src/runtime/asm_mips64x.s @@ -231,12 +231,14 @@ TEXT runtime·morestack(SB),NOSPLIT,$-8-0 // Cannot grow scheduler stack (m->g0). MOVV g_m(g), R7 MOVV m_g0(R7), R8 - BNE g, R8, 2(PC) + BNE g, R8, 3(PC) + JAL runtime·badmorestackg0(SB) JAL runtime·abort(SB) // Cannot grow signal stack (m->gsignal). MOVV m_gsignal(R7), R8 - BNE g, R8, 2(PC) + BNE g, R8, 3(PC) + JAL runtime·badmorestackgsignal(SB) JAL runtime·abort(SB) // Called from f. diff --git a/src/runtime/asm_ppc64x.s b/src/runtime/asm_ppc64x.s index 8b5ea45082..251dc1b564 100644 --- a/src/runtime/asm_ppc64x.s +++ b/src/runtime/asm_ppc64x.s @@ -284,13 +284,15 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 MOVD g_m(g), R7 MOVD m_g0(R7), R8 CMP g, R8 - BNE 2(PC) + BNE 3(PC) + BL runtime·badmorestackg0(SB) BL runtime·abort(SB) // Cannot grow signal stack (m->gsignal). MOVD m_gsignal(R7), R8 CMP g, R8 - BNE 2(PC) + BNE 3(PC) + BL runtime·badmorestackgsignal(SB) BL runtime·abort(SB) // Called from f. diff --git a/src/runtime/asm_s390x.s b/src/runtime/asm_s390x.s index 70e3b5e859..9ed4d91868 100644 --- a/src/runtime/asm_s390x.s +++ b/src/runtime/asm_s390x.s @@ -279,13 +279,15 @@ TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 // Cannot grow scheduler stack (m->g0). MOVD g_m(g), R7 MOVD m_g0(R7), R8 - CMPBNE g, R8, 2(PC) + CMPBNE g, R8, 3(PC) + BL runtime·badmorestackg0(SB) BL runtime·abort(SB) // Cannot grow signal stack (m->gsignal). MOVD m_gsignal(R7), R8 CMP g, R8 - BNE 2(PC) + BNE 3(PC) + BL runtime·badmorestackgsignal(SB) BL runtime·abort(SB) // Called from f. diff --git a/src/runtime/proc.go b/src/runtime/proc.go index cb0004d233..937135961a 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -381,6 +381,24 @@ func badreflectcall() { 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 { gp := getg() return gp.lockedm != nil && gp.m.lockedg != nil