]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix program termination when main goroutine calls Goexit
authorDmitriy Vyukov <dvyukov@google.com>
Tue, 15 Apr 2014 15:48:17 +0000 (19:48 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Tue, 15 Apr 2014 15:48:17 +0000 (19:48 +0400)
Do not consider idle finalizer/bgsweep/timer goroutines as doing something useful.
We can't simply set isbackground for the whole lifetime of the goroutines,
because when finalizer goroutine calls user function, we do want to consider it
as doing something useful.
This is borken due to timers for quite some time.
With background sweep is become even more broken.
Fixes #7784.

LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/87960044

src/pkg/runtime/crash_test.go
src/pkg/runtime/mgc0.c
src/pkg/runtime/time.goc

index 0e5056d822bd5d58588c2486e0eae4f49ce26faa..cd9520b165e3f56764270ecb4fcbd0f1fb796365 100644 (file)
@@ -144,6 +144,15 @@ panic: again
 
 }
 
+func TestGoexitExit(t *testing.T) {
+       output := executeTest(t, goexitExitSource, nil)
+       want := ""
+       if output != want {
+               t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want)
+       }
+
+}
+
 const crashSource = `
 package main
 
@@ -310,3 +319,22 @@ func main() {
        panic("again")
 }
 `
+
+const goexitExitSource = `
+package main
+
+import (
+       "runtime"
+       "time"
+)
+
+func main() {
+       go func() {
+               time.Sleep(time.Millisecond)
+       }()
+       i := 0
+       runtime.SetFinalizer(&i, func(p *int) {})
+       runtime.GC()
+       runtime.Goexit()
+}
+`
index 26a18d36c720c64f8f8dd47dbfb74d7d9397fc8c..be7f27e396f58f4007f2280a878b3865503bfc3f 100644 (file)
@@ -1973,7 +1973,9 @@ bgsweep(void)
                        continue;
                }
                sweep.parked = true;
+               g->isbackground = true;
                runtime·parkunlock(&gclock, "GC sweep wait");
+               g->isbackground = false;
        }
 }
 
@@ -2618,7 +2620,9 @@ runfinq(void)
                finq = nil;
                if(fb == nil) {
                        runtime·fingwait = true;
+                       g->isbackground = true;
                        runtime·parkunlock(&finlock, "finalizer wait");
+                       g->isbackground = false;
                        continue;
                }
                runtime·unlock(&finlock);
index d9393d7c8a4926d27a610457a386c2ad2657aabf..195c5c41a37713c635fbc69d934687ac02c7ab5b 100644 (file)
@@ -238,7 +238,9 @@ timerproc(void)
                if(delta < 0) {
                        // No timers left - put goroutine to sleep.
                        timers.rescheduling = true;
+                       g->isbackground = true;
                        runtime·parkunlock(&timers, "timer goroutine (idle)");
+                       g->isbackground = false;
                        continue;
                }
                // At least one timer pending.  Sleep until then.