diff --git a/doc/go1.3.html b/doc/go1.3.html
index 916ed04d25a..466eeb1a16e 100644
--- a/doc/go1.3.html
+++ b/doc/go1.3.html
@@ -379,6 +379,15 @@ In particular, it only calls LookPath
+
+If the main goroutine calls
+runtime.Goexit
+and all other goroutines finish execution, the program now always crashes,
+reporting a detected deadlock.
+Earlier versions of Go handled this situation inconsistently: most instances
+were reported as deadlocks, but some trivial cases exited cleanly instead.
+
+
The CanBackquote
function in the strconv package
diff --git a/src/pkg/runtime/crash_test.go b/src/pkg/runtime/crash_test.go
index cd9520b165e..dbcd9486de4 100644
--- a/src/pkg/runtime/crash_test.go
+++ b/src/pkg/runtime/crash_test.go
@@ -111,8 +111,9 @@ func TestLockedDeadlock2(t *testing.T) {
func TestGoexitDeadlock(t *testing.T) {
output := executeTest(t, goexitDeadlockSource, nil)
- if output != "" {
- t.Fatalf("expected no output, got:\n%s", output)
+ want := "no goroutines (main called runtime.Goexit) - deadlock!"
+ if !strings.Contains(output, want) {
+ t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
}
}
@@ -144,13 +145,12 @@ panic: again
}
-func TestGoexitExit(t *testing.T) {
+func TestGoexitCrash(t *testing.T) {
output := executeTest(t, goexitExitSource, nil)
- want := ""
- if output != want {
- t.Fatalf("output:\n%s\n\nwanted:\n%s", output, want)
+ want := "no goroutines (main called runtime.Goexit) - deadlock!"
+ if !strings.Contains(output, want) {
+ t.Fatalf("output:\n%s\n\nwant output containing: %s", output, want)
}
-
}
const crashSource = `
diff --git a/src/pkg/runtime/extern.go b/src/pkg/runtime/extern.go
index 0c5041d38b1..2466911dd69 100644
--- a/src/pkg/runtime/extern.go
+++ b/src/pkg/runtime/extern.go
@@ -79,6 +79,11 @@ func Gosched()
// Goexit terminates the goroutine that calls it. No other goroutine is affected.
// Goexit runs all deferred calls before terminating the goroutine.
+//
+// Calling Goexit from the main goroutine terminates that goroutine
+// without func main returning. Since func main has not returned,
+// the program continues execution of other goroutines.
+// If all other goroutines exit, the program crashes.
func Goexit()
// Caller reports file and line number information about function invocations on
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index 6b5c031c874..52b02d94bb4 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -2501,7 +2501,7 @@ checkdead(void)
}
runtime·unlock(&allglock);
if(grunning == 0) // possible if main goroutine calls runtime·Goexit()
- runtime·exit(0);
+ runtime·throw("no goroutines (main called runtime.Goexit) - deadlock!");
m->throwing = -1; // do not dump full stacks
runtime·throw("all goroutines are asleep - deadlock!");
}