summaryrefslogtreecommitdiff
path: root/src/pkg/runtime/stack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/runtime/stack.c')
-rw-r--r--src/pkg/runtime/stack.c24
1 files changed, 22 insertions, 2 deletions
diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c
index 3993a372e..f0861e408 100644
--- a/src/pkg/runtime/stack.c
+++ b/src/pkg/runtime/stack.c
@@ -714,8 +714,8 @@ adjustdefers(G *gp, AdjustInfo *adjinfo)
if(adjinfo->oldstk <= (byte*)d && (byte*)d < adjinfo->oldbase) {
// The Defer record is on the stack. Its fields will
// get adjusted appropriately.
- // This only happens for runtime.main now, but a compiler
- // optimization could do more of this.
+ // This only happens for runtime.main and runtime.gopanic now,
+ // but a compiler optimization could do more of this.
*dp = (Defer*)((byte*)d + adjinfo->delta);
continue;
}
@@ -753,6 +753,25 @@ adjustdefers(G *gp, AdjustInfo *adjinfo)
}
static void
+adjustpanics(G *gp, AdjustInfo *adjinfo)
+{
+ Panic *p;
+
+ // only the topmost panic is on the current stack
+ p = gp->panic;
+ if(p == nil)
+ return;
+ if(p->link != nil) {
+ // only the topmost panic can be on the current stack
+ // (because panic runs defers on a new stack)
+ if(adjinfo->oldstk <= (byte*)p->link && (byte*)p->link < adjinfo->oldbase)
+ runtime·throw("two panics on one stack");
+ }
+ if(adjinfo->oldstk <= (byte*)p && (byte*)p < adjinfo->oldbase)
+ gp->panic = (Panic*)((byte*)p + adjinfo->delta);
+}
+
+static void
adjustsudogs(G *gp, AdjustInfo *adjinfo)
{
SudoG *s;
@@ -811,6 +830,7 @@ copystack(G *gp, uintptr nframes, uintptr newsize)
// adjust other miscellaneous things that have pointers into stacks.
adjustctxt(gp, &adjinfo);
adjustdefers(gp, &adjinfo);
+ adjustpanics(gp, &adjinfo);
adjustsudogs(gp, &adjinfo);
// copy the stack (including Stktop) to the new location