]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: improve error messages after allocating a stack that is too big
authorPaschalis Tsilias <paschalis.tsilias@gmail.com>
Fri, 18 Sep 2020 16:15:41 +0000 (19:15 +0300)
committerGiovanni Bajo <rasky@develer.com>
Sun, 20 Sep 2020 09:54:44 +0000 (09:54 +0000)
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>
src/runtime/debug/garbage.go
src/runtime/proc.go
src/runtime/stack.go

index e36e54f12d34d559f170531c453147dc6171011e..00f92c3ddfb69c6bde4fed19ad54cc0003d12b15 100644 (file)
@@ -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
index 739745aa265a4d1198267504f39f49c3e42ddaac..f4665220ae991f91bbd35b61ee597b6caf61f5fd 100644 (file)
@@ -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
 
index 821c2e84360d3c6df8e28bb23ae879c013e955f3..613126c7084038781b0716e48753a3dcd49ec4f7 100644 (file)
@@ -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")
        }