mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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
This commit is contained in:
parent
1569628725
commit
e678ab4e37
3 changed files with 17 additions and 0 deletions
|
|
@ -1704,14 +1704,28 @@ syscall·runtime_BeforeFork(void)
|
||||||
m->locks++;
|
m->locks++;
|
||||||
if(m->profilehz != 0)
|
if(m->profilehz != 0)
|
||||||
runtime·resetcpuprofiler(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.
|
// Called from syscall package after fork in parent.
|
||||||
|
#pragma textflag NOSPLIT
|
||||||
void
|
void
|
||||||
syscall·runtime_AfterFork(void)
|
syscall·runtime_AfterFork(void)
|
||||||
{
|
{
|
||||||
int32 hz;
|
int32 hz;
|
||||||
|
|
||||||
|
// See the comment in runtime_BeforeFork.
|
||||||
|
g->stackguard0 = m->forkstackguard;
|
||||||
|
g->stackguard = m->forkstackguard;
|
||||||
|
m->forkstackguard = 0;
|
||||||
|
|
||||||
hz = runtime·sched.profilehz;
|
hz = runtime·sched.profilehz;
|
||||||
if(hz != 0)
|
if(hz != 0)
|
||||||
runtime·resetcpuprofiler(hz);
|
runtime·resetcpuprofiler(hz);
|
||||||
|
|
|
||||||
|
|
@ -367,6 +367,7 @@ struct M
|
||||||
bool needextram;
|
bool needextram;
|
||||||
bool (*waitunlockf)(G*, void*);
|
bool (*waitunlockf)(G*, void*);
|
||||||
void* waitlock;
|
void* waitlock;
|
||||||
|
uintptr forkstackguard;
|
||||||
#ifdef GOOS_windows
|
#ifdef GOOS_windows
|
||||||
void* thread; // thread handle
|
void* thread; // thread handle
|
||||||
// these are here because they are too large to be on the stack
|
// these are here because they are too large to be on the stack
|
||||||
|
|
|
||||||
|
|
@ -583,6 +583,8 @@ runtime·newstack(void)
|
||||||
Gobuf label;
|
Gobuf label;
|
||||||
bool newstackcall;
|
bool newstackcall;
|
||||||
|
|
||||||
|
if(m->forkstackguard)
|
||||||
|
runtime·throw("split stack after fork");
|
||||||
if(m->morebuf.g != m->curg) {
|
if(m->morebuf.g != m->curg) {
|
||||||
runtime·printf("runtime: newstack called from g=%p\n"
|
runtime·printf("runtime: newstack called from g=%p\n"
|
||||||
"\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
|
"\tm=%p m->curg=%p m->g0=%p m->gsignal=%p\n",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue