]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: skip doInit of plugins in runtime.main
authorWang Deyu <wangdeyu.2021@bytedance.com>
Wed, 20 Aug 2025 13:33:42 +0000 (21:33 +0800)
committerGopher Robot <gobot@golang.org>
Mon, 25 Aug 2025 17:54:23 +0000 (10:54 -0700)
Plugins may be loaded in the user's init code.
If loading fails, md.bad is true, and doInit should not be executed.
If loading succeeds, the plugin must run modulesinit and typelinksinit
before doInit. Here is not protected by pluginsMu, and in concurrent
scenarios it is possible to obtain the moduledata of the plugin that
is still in the loading process.
Any added modules after loop starts will do their own doInit calls.
This fixes the issue introduced by CL 520375.

Fixes #75102

Change-Id: I48e91ae21615a0c54176875a6a2dea8e1dade906
Reviewed-on: https://go-review.googlesource.com/c/go/+/697675
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/cmd/cgo/internal/testplugin/plugin_test.go
src/cmd/cgo/internal/testplugin/testdata/issue75102/main.go [new file with mode: 0644]
src/cmd/cgo/internal/testplugin/testdata/issue75102/plugin.go [new file with mode: 0644]
src/runtime/proc.go

index d2d998e5f439b4ea1c0ca1ea8b87b5783b8305c6..5bff81092cad8274684c555f2624b6f1a09896b0 100644 (file)
@@ -422,3 +422,11 @@ func TestIssue67976(t *testing.T) {
        globalSkip(t)
        goCmd(t, "build", "-buildmode=plugin", "-o", "issue67976.so", "./issue67976/plugin.go")
 }
+
+func TestIssue75102(t *testing.T) {
+       globalSkip(t)
+       // add gcflags different from the executable file to trigger plugin open failed.
+       goCmd(t, "build", "-gcflags=all=-N -l", "-buildmode=plugin", "-o", "issue75102.so", "./issue75102/plugin.go")
+       goCmd(t, "build", "-o", "issue75102.exe", "./issue75102/main.go")
+       run(t, "./issue75102.exe")
+}
diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue75102/main.go b/src/cmd/cgo/internal/testplugin/testdata/issue75102/main.go
new file mode 100644 (file)
index 0000000..217a47b
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2025 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.
+
+package main
+
+import (
+       "fmt"
+       "plugin"
+)
+
+func init() {
+       _, err := plugin.Open("issue75102.so")
+       if err == nil {
+               panic("unexpected success to open a different version plugin")
+       }
+}
+
+func main() {
+       fmt.Println("done")
+}
diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue75102/plugin.go b/src/cmd/cgo/internal/testplugin/testdata/issue75102/plugin.go
new file mode 100644 (file)
index 0000000..d09137d
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2025 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.
+
+package main
+
+func init() {
+       panic("unexpected call to init")
+}
+
+func main() {}
index 68647d771fe9528f87261c50ff0686f2a12900e0..5b1c4906af3d1da42788a12e4e32e875d293fcf0 100644 (file)
@@ -252,8 +252,12 @@ func main() {
        // by package plugin). Run through the modules in dependency
        // order (the order they are initialized by the dynamic
        // loader, i.e. they are added to the moduledata linked list).
-       for m := &firstmoduledata; m != nil; m = m.next {
+       last := lastmoduledatap // grab before loop starts. Any added modules after this point will do their own doInit calls.
+       for m := &firstmoduledata; true; m = m.next {
                doInit(m.inittasks)
+               if m == last {
+                       break
+               }
        }
 
        // Disable init tracing after main init done to avoid overhead