aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/runtime/proc.c
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2013-07-26 13:54:44 -0400
committerRuss Cox <rsc@golang.org>2013-07-26 13:54:44 -0400
commit14062efb16e3c69adaf655d0b545189036929368 (patch)
tree844645ceabf0f945a109a1c4992a0866745984ff /src/pkg/runtime/proc.c
parentf8a850b250655bd26f5da4cfe7299b4a32be28fa (diff)
downloadgo-14062efb16e3c69adaf655d0b545189036929368.tar.xz
runtime: handle runtime.Goexit during init
Fixes #5963. R=golang-dev, dsymonds, dvyukov CC=golang-dev https://golang.org/cl/11879045
Diffstat (limited to 'src/pkg/runtime/proc.c')
-rw-r--r--src/pkg/runtime/proc.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 135a112f52..6e3c274560 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -160,10 +160,14 @@ extern void main·main(void);
static FuncVal scavenger = {runtime·MHeap_Scavenger};
+static FuncVal initDone = { runtime·unlockOSThread };
+
// The main goroutine.
void
runtime·main(void)
{
+ Defer d;
+
newm(sysmon, nil);
// Lock the main goroutine onto this, the main OS thread,
@@ -173,10 +177,24 @@ runtime·main(void)
// by calling runtime.LockOSThread during initialization
// to preserve the lock.
runtime·lockOSThread();
+
+ // Defer unlock so that runtime.Goexit during init does the unlock too.
+ d.fn = &initDone;
+ d.siz = 0;
+ d.link = g->defer;
+ d.argp = (void*)-1;
+ d.special = true;
+ d.free = false;
+ g->defer = &d;
+
if(m != &runtime·m0)
runtime·throw("runtime·main not on m0");
runtime·newproc1(&scavenger, nil, 0, 0, runtime·main);
main·init();
+
+ if(g->defer != &d || d.fn != &initDone)
+ runtime·throw("runtime: bad defer entry after init");
+ g->defer = d.link;
runtime·unlockOSThread();
main·main();