aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime
diff options
context:
space:
mode:
authorDmitriy Vyukov <dvyukov@google.com>2014-03-13 17:41:08 +0400
committerDmitriy Vyukov <dvyukov@google.com>2014-03-13 17:41:08 +0400
commite678ab4e375659fea86b17557c23673033cf897c (patch)
tree4572fb56152de8e44ae6482a9a45cd2743220ecd /src/pkg/runtime
parent156962872575382697a0487030cd5777312d6d0c (diff)
downloadgo-e678ab4e375659fea86b17557c23673033cf897c.tar.xz
runtime: detect stack split after fork
This check would allowed to easily prevent issue 7511. Update #7511 LGTM=rsc R=rsc, aram CC=golang-codereviews https://golang.org/cl/75260043
Diffstat (limited to 'src/pkg/runtime')
-rw-r--r--src/pkg/runtime/proc.c14
-rw-r--r--src/pkg/runtime/runtime.h1
-rw-r--r--src/pkg/runtime/stack.c2
3 files changed, 17 insertions, 0 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index d3ad740136..e11f9b18ac 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -1704,14 +1704,28 @@ syscall·runtime_BeforeFork(void)
m->locks++;
if(m->profilehz != 0)
runtime·resetcpuprofiler(0);
+
+ // This function is called before fork in syscall package.
+ // Code between fork and exec must not allocate memory nor even try to grow stack.
+ // Here we spoil g->stackguard to reliably detect any attempts to grow stack.
+ // runtime_AfterFork will undo this in parent process, but not in child.
+ m->forkstackguard = g->stackguard;
+ g->stackguard0 = StackPreempt-1;
+ g->stackguard = StackPreempt-1;
}
// Called from syscall package after fork in parent.
+#pragma textflag NOSPLIT
void
syscall·runtime_AfterFork(void)
{
int32 hz;
+ // See the comment in runtime_BeforeFork.
+ g->stackguard0 = m->forkstackguard;
+ g->stackguard = m->forkstackguard;
+ m->forkstackguard = 0;
+
hz = runtime·sched.profilehz;
if(hz != 0)
runtime·resetcpuprofiler(hz);
diff --git a/src/pkg/runtime/runtime.h b/src/pkg/runtime/runtime.h
index ecff533f59..8e5e9a1294 100644
--- a/src/pkg/runtime/runtime.h
+++ b/src/pkg/runtime/runtime.h
@@ -367,6 +367,7 @@ struct M
bool needextram;
bool (*waitunlockf)(G*, void*);
void* waitlock;
+ uintptr forkstackguard;
#ifdef GOOS_windows
void* thread; // thread handle
// these are here because they are too large to be on the stack
diff --git a/src/pkg/runtime/stack.c b/src/pkg/runtime/stack.c
index bb7a32f8ae..d580665e2b 100644
--- a/src/pkg/runtime/stack.c
+++ b/src/pkg/runtime/stack.c
@@ -583,6 +583,8 @@ runtime·newstack(void)
Gobuf label;
bool newstackcall;
+ if(m->forkstackguard)
+ runtime·throw("split stack after fork");
if(m->morebuf.g != m->curg) {
runtime·printf("runtime: newstack called from g=%p\n"
"\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",