]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: work around false negative in deadlock detection
authorRuss Cox <rsc@golang.org>
Tue, 27 Mar 2012 16:22:19 +0000 (12:22 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 27 Mar 2012 16:22:19 +0000 (12:22 -0400)
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

src/pkg/runtime/proc.c
test/fixedbugs/bug429.go [new file with mode: 0644]
test/golden.out

index 962f748ce860f921bfa8b6d9d9a2a02c75e35897..04a9926283bd397bbc568f2665a194470f924ba5 100644 (file)
@@ -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 (file)
index 0000000..c1bd1d4
--- /dev/null
@@ -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 {}
+}
index 764f561969dd6b19531478f40309fe2eac036b6d..376af8e53ccd68e13a3f8e37a9639c98e3e0ed3d 100644 (file)
@@ -15,6 +15,9 @@
 
 == fixedbugs/
 
+=========== fixedbugs/bug429.go
+throw: all goroutines are asleep - deadlock!
+
 == bugs/
 
 =========== bugs/bug395.go