aboutsummaryrefslogtreecommitdiff
path: root/src/runtime
diff options
context:
space:
mode:
authorqiulaidongfeng <2645477756@qq.com>2024-09-09 09:01:23 +0000
committerGopher Robot <gobot@golang.org>2024-09-10 21:10:43 +0000
commit3da4281df1b0c7ea11b524ff19fc2f409b8e58c0 (patch)
tree10de5bee7a0c41330cc20a66d3b7d83ed3cd9878 /src/runtime
parent77e42fdeaf98d241dc09f4eb92e09225aea8f4c3 (diff)
downloadgo-3da4281df1b0c7ea11b524ff19fc2f409b8e58c0.tar.xz
runtime: Goexit on C-created thread report more useful error message
Fixes #68275 Change-Id: I47b7a2092f1b4d48aebf437db4e329815c956bb9 GitHub-Last-Rev: b89bf3cab7f9f7611122f535914f2788564643c5 GitHub-Pull-Request: golang/go#69126 Reviewed-on: https://go-review.googlesource.com/c/go/+/609296 Reviewed-by: Tim King <taking@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
Diffstat (limited to 'src/runtime')
-rw-r--r--src/runtime/panic.go2
-rw-r--r--src/runtime/proc.go3
-rw-r--r--src/runtime/proc_test.go10
-rw-r--r--src/runtime/testdata/testprogcgo/callback.go11
4 files changed, 26 insertions, 0 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index bd1ea096aa..ed08bf4f30 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -614,6 +614,8 @@ func deferreturn() {
// 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.
+//
+// It crashes if called from a thread not created by the Go runtime.
func Goexit() {
// Create a panic object for Goexit, so we can recognize when it might be
// bypassed by a recover().
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index c4db86225d..0909d138ff 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -4321,6 +4321,9 @@ func gdestroy(gp *g) {
if locked && mp.lockedInt != 0 {
print("runtime: mp.lockedInt = ", mp.lockedInt, "\n")
+ if mp.isextra {
+ throw("runtime.Goexit called in a thread that was not created by the Go runtime")
+ }
throw("exited a goroutine internally locked to the OS thread")
}
gfput(pp, gp)
diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go
index a930ea707f..0a54240984 100644
--- a/src/runtime/proc_test.go
+++ b/src/runtime/proc_test.go
@@ -1158,3 +1158,13 @@ func TestBigGOMAXPROCS(t *testing.T) {
t.Errorf("output:\n%s\nwanted:\nunknown function: NonexistentTest", output)
}
}
+
+func TestCgoToGoCallGoexit(t *testing.T) {
+ if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
+ t.Skipf("no pthreads on %s", runtime.GOOS)
+ }
+ output := runTestProg(t, "testprogcgo", "CgoToGoCallGoexit")
+ if !strings.Contains(output, "runtime.Goexit called in a thread that was not created by the Go runtime") {
+ t.Fatalf("output should contain %s, got %s", "runtime.Goexit called in a thread that was not created by the Go runtime", output)
+ }
+}
diff --git a/src/runtime/testdata/testprogcgo/callback.go b/src/runtime/testdata/testprogcgo/callback.go
index 319572fe10..39993f13a6 100644
--- a/src/runtime/testdata/testprogcgo/callback.go
+++ b/src/runtime/testdata/testprogcgo/callback.go
@@ -38,10 +38,21 @@ import (
func init() {
register("CgoCallbackGC", CgoCallbackGC)
+ register("CgoToGoCallGoexit", CgoToGoCallGoexit)
}
+func CgoToGoCallGoexit() {
+ goexit = true
+ C.foo()
+}
+
+var goexit = false
+
//export go_callback
func go_callback() {
+ if goexit {
+ runtime.Goexit()
+ }
if e := extraMInUse.Load(); e == 0 {
fmt.Printf("in callback extraMInUse got %d want >0\n", e)
os.Exit(1)