aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémy Oudompheng <oudomphe@phare.normalesup.org>2012-03-26 23:06:20 -0400
committerRuss Cox <rsc@golang.org>2012-03-26 23:06:20 -0400
commit84bb2547fb81f00c563e3cbe0f310307980d7408 (patch)
treebc88907d8327691a3267bcd43f55f9abea3ccaf0
parent603a44c50f8028500ff012de2549313cfcbc96c6 (diff)
downloadgo-84bb2547fb81f00c563e3cbe0f310307980d7408.tar.gz
go-84bb2547fb81f00c563e3cbe0f310307980d7408.zip
runtime: restore deadlock detection in the simplest case.
Fixes #3342. R=iant, r, dave, rsc CC=golang-dev, remy https://golang.org/cl/5844051
-rw-r--r--src/pkg/runtime/mheap.c3
-rw-r--r--src/pkg/runtime/proc.c19
-rw-r--r--test/fixedbugs/bug429.go13
-rw-r--r--test/golden.out3
4 files changed, 33 insertions, 5 deletions
diff --git a/src/pkg/runtime/mheap.c b/src/pkg/runtime/mheap.c
index c877bfca91..9dd50835e7 100644
--- a/src/pkg/runtime/mheap.c
+++ b/src/pkg/runtime/mheap.c
@@ -358,6 +358,9 @@ runtime·MHeap_Scavenger(void)
h = &runtime·mheap;
for(k=0;; k++) {
+ // Return to the scheduler in case the rest of the world is deadlocked.
+ runtime·gosched();
+
runtime·noteclear(&note);
runtime·entersyscall();
runtime·notetsleep(&note, tick);
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 962f748ce8..509d8208c8 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -521,6 +521,16 @@ mnextg(M *m, G *g)
}
}
+// Check for a deadlock situation.
+static void
+checkdeadlock(void) {
+ if((scvg == nil && runtime·sched.grunning == 0) ||
+ (scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
+ (scvg->status == Grunnable || scvg->status == Grunning || scvg->status == Gsyscall))) {
+ runtime·throw("all goroutines are asleep - deadlock!");
+ }
+}
+
// Get the next goroutine that m should run.
// Sched must be locked on entry, is unlocked on exit.
// Makes sure that at most $GOMAXPROCS g's are
@@ -570,6 +580,9 @@ top:
continue;
}
runtime·sched.grunning++;
+ // The work could actually have been the sole scavenger
+ // goroutine. Look for deadlock situation.
+ checkdeadlock();
schedunlock();
return gp;
}
@@ -591,11 +604,7 @@ top:
}
// Look for deadlock situation.
- if((scvg == nil && runtime·sched.grunning == 0) ||
- (scvg != nil && runtime·sched.grunning == 1 && runtime·sched.gwait == 0 &&
- (scvg->status == Grunning || scvg->status == Gsyscall))) {
- runtime·throw("all goroutines are asleep - deadlock!");
- }
+ checkdeadlock();
m->nextg = nil;
m->waitnextg = 1;
diff --git a/test/fixedbugs/bug429.go b/test/fixedbugs/bug429.go
new file mode 100644
index 0000000000..991a371377
--- /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