1
0
mirror of https://github.com/golang/go synced 2024-11-25 01:57:56 -07:00

runtime: work around false negative in deadlock detection

Not a complete fix for issue 3342, but fixes the trivial case.
There may still be a race in the instants before and after
a scavenger-induced garbage collection.

Intended to be "obviously safe": a call to runtime·gosched
before main.main is no different than a call to runtime.Gosched
at the beginning of main.main, and it is (or had better be)
safe to call runtime.Gosched at any point during main.

Update #3342.

R=iant
CC=golang-dev
https://golang.org/cl/5919052
This commit is contained in:
Russ Cox 2012-03-27 12:22:19 -04:00
parent 9d7076b178
commit 5eb007dede
3 changed files with 35 additions and 0 deletions

View File

@ -236,6 +236,11 @@ runtime·main(void)
if(!runtime·sched.lockmain) if(!runtime·sched.lockmain)
runtime·UnlockOSThread(); runtime·UnlockOSThread();
// The deadlock detection has false negatives.
// Let scvg start up, to eliminate the false negative
// for the trivial program func main() { select{} }.
runtime·gosched();
main·main(); main·main();
runtime·exit(0); runtime·exit(0);
for(;;) for(;;)
@ -591,6 +596,20 @@ top:
} }
// Look for deadlock situation. // Look for deadlock situation.
// There is a race with the scavenger that causes false negatives:
// if the scavenger is just starting, then we have
// scvg != nil && grunning == 0 && gwait == 0
// and we do not detect a deadlock. It is possible that we should
// add that case to the if statement here, but it is too close to Go 1
// to make such a subtle change. Instead, we work around the
// false negative in trivial programs by calling runtime.gosched
// from the main goroutine just before main.main.
// See runtime·main above.
//
// On a related note, it is also possible that the scvg == nil case is
// wrong and should include gwait, but that does not happen in
// standard Go programs, which all start the scavenger.
//
if((scvg == nil && runtime·sched.grunning == 0) || if((scvg == nil && runtime·sched.grunning == 0) ||
(scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 && (scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
(scvg->status == Grunning || scvg->status == Gsyscall))) { (scvg->status == Grunning || scvg->status == Gsyscall))) {

13
test/fixedbugs/bug429.go Normal file
View File

@ -0,0 +1,13 @@
// $G $D/$F.go && $L $F.$A && ! ./$A.out || echo BUG: bug429
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Should print deadlock message, not hang.
package main
func main() {
select {}
}

View File

@ -15,6 +15,9 @@
== fixedbugs/ == fixedbugs/
=========== fixedbugs/bug429.go
throw: all goroutines are asleep - deadlock!
== bugs/ == bugs/
=========== bugs/bug395.go =========== bugs/bug395.go