aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorPaschalis Tsilias <paschalis.tsilias@gmail.com>2020-09-18 19:15:41 +0300
committerGiovanni Bajo <rasky@develer.com>2020-09-20 09:54:44 +0000
commit331614c4daa5504ddfe35a96371cc34783d14cf1 (patch)
treeef3eab158a8ae1b62cc860a1710e42fbcb81de1c /src/runtime
parenta3868028ac8470d1ab7782614707bb90925e7fe3 (diff)
downloadgo-331614c4daa5504ddfe35a96371cc34783d14cf1.tar.xz
runtime: improve error messages after allocating a stack that is too big
In the current implementation, we can observe crashes after calling debug.SetMaxStack and allocating a stack larger than 4GB since stackalloc works with 32-bit sizes. To avoid this, we define an upper limit as the largest feasible point we can grow a stack to and provide a better error message when we get a stack overflow. Fixes #41228 Change-Id: I55fb0a824f47ed9fb1fcc2445a4dfd57da9ef8d4 Reviewed-on: https://go-review.googlesource.com/c/go/+/255997 Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Trust: Giovanni Bajo <rasky@develer.com> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/debug/garbage.go2
-rw-r--r--src/runtime/proc.go5
-rw-r--r--src/runtime/stack.go10
3 files changed, 15 insertions, 2 deletions
diff --git a/src/runtime/debug/garbage.go b/src/runtime/debug/garbage.go
index e36e54f12d..00f92c3ddf 100644
--- a/src/runtime/debug/garbage.go
+++ b/src/runtime/debug/garbage.go
@@ -106,6 +106,8 @@ func FreeOSMemory() {
// the program crashes.
// SetMaxStack returns the previous setting.
// The initial setting is 1 GB on 64-bit systems, 250 MB on 32-bit systems.
+// There may be a system-imposed maximum stack limit regardless
+// of the value provided to SetMaxStack.
//
// SetMaxStack is useful mainly for limiting the damage done by
// goroutines that enter an infinite recursion. It only limits future
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 739745aa26..f4665220ae 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -128,6 +128,11 @@ func main() {
maxstacksize = 250000000
}
+ // An upper limit for max stack size. Used to avoid random crashes
+ // after calling SetMaxStack and trying to allocate a stack that is too big,
+ // since stackalloc works with 32-bit sizes.
+ maxstackceiling = 2 * maxstacksize
+
// Allow newproc to start new Ms.
mainStarted = true
diff --git a/src/runtime/stack.go b/src/runtime/stack.go
index 821c2e8436..613126c708 100644
--- a/src/runtime/stack.go
+++ b/src/runtime/stack.go
@@ -497,6 +497,8 @@ func stackfree(stk stack) {
var maxstacksize uintptr = 1 << 20 // enough until runtime.main sets it for real
+var maxstackceiling = maxstacksize
+
var ptrnames = []string{
0: "scalar",
1: "ptr",
@@ -1050,8 +1052,12 @@ func newstack() {
}
}
- if newsize > maxstacksize {
- print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
+ if newsize > maxstacksize || newsize > maxstackceiling {
+ if maxstacksize < maxstackceiling {
+ print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
+ } else {
+ print("runtime: goroutine stack exceeds ", maxstackceiling, "-byte limit\n")
+ }
print("runtime: sp=", hex(sp), " stack=[", hex(gp.stack.lo), ", ", hex(gp.stack.hi), "]\n")
throw("stack overflow")
}