Commit 55e0f36f authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: fix program termination when main goroutine calls Goexit

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
parent d826b2ed
......@@ -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()
}
`
......@@ -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);
......
......@@ -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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment