mirror of
https://github.com/golang/go
synced 2024-11-19 20:54:39 -07:00
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
This commit is contained in:
parent
d826b2ed98
commit
55e0f36fb4
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user