aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2012-03-27 12:22:19 -0400
committerRuss Cox <rsc@golang.org>2012-03-27 12:22:19 -0400
commit5eb007dedeb59a52a3000202dcb162a3677a384b (patch)
tree12a2cef73e5e622222822d2a25c08c662e4fb084
parent9d7076b178e3b688a8421a8ce02466a3701d31a0 (diff)
downloadgo-5eb007dedeb59a52a3000202dcb162a3677a384b.tar.gz
go-5eb007dedeb59a52a3000202dcb162a3677a384b.zip
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
-rw-r--r--src/pkg/runtime/proc.c19
-rw-r--r--test/fixedbugs/bug429.go13
-rw-r--r--test/golden.out3
3 files changed, 35 insertions, 0 deletions
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 962f748ce8..04a9926283 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -236,6 +236,11 @@ runtime·main(void)
if(!runtime·sched.lockmain)
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();
runtime·exit(0);
for(;;)
@@ -591,6 +596,20 @@ top:
}
// 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) ||
(scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
(scvg->status == Grunning || scvg->status == Gsyscall))) {
diff --git a/test/fixedbugs/bug429.go b/test/fixedbugs/bug429.go
new file mode 100644
index 0000000000..c1bd1d4bb9
--- /dev/null
+++ b/test/fixedbugs/bug429.go
@@ -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 {}
+}
diff --git a/test/golden.out b/test/golden.out
index 764f561969..376af8e53c 100644
--- a/test/golden.out
+++ b/test/golden.out
@@ -15,6 +15,9 @@
== fixedbugs/
+=========== fixedbugs/bug429.go
+throw: all goroutines are asleep - deadlock!
+
== bugs/
=========== bugs/bug395.go