Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plugin: report the version of Go used to build a plugin when a mismatch occurs #63290

Open
mfreeman451 opened this issue Sep 29, 2023 · 3 comments
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@mfreeman451
Copy link

What version of Go are you using (go version)?

$ go version
go version go1.21.1 linux/amd64

Does this issue reproduce with the latest release?

Y

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/mfreeman/.cache/go-build'
GOENV='/home/mfreeman/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOOS='linux'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.21.1'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build4277136579=/tmp/go-build -gno-record-gcc-switches'

What did you do?

go build -buildmode=plugin -o ./handler.so ./main.go

Then when I tried to use it with another program:

2023/09/29 02:11:29 main.go:26: plugin error: plugin.Open("/plugin/handler"): plugin was built with a different version of package google.golang.org/protobuf/internal/pragma

What did you expect to see?

It should tell me what the different version is so I can match it.

What did you see instead?

Nothing other than a not very useful message telling me that I have the wrong version, but not what the correct version should be.

@mdlayher mdlayher changed the title affected/package: go plugin system plugin: report the version of Go used to build a plugin when a mismatch occurs Sep 29, 2023
@seankhliao seankhliao added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Sep 29, 2023
@cherrymui
Copy link
Member

You can run go version -m handler.so and go version -m <main_executable> to find out the versions and how they differ. Would that be helpful?

@mfreeman451
Copy link
Author

mfreeman451 commented Sep 29, 2023 via email

@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Oct 9, 2023
@mknyszek mknyszek added this to the Backlog milestone Oct 11, 2023
@quantonganh
Copy link
Contributor

You can run go version -m handler.so and go version -m <main_executable> to find out the versions and how they differ. Would that be helpful?

I'm afraid that there are some cases where go version -m cannot help.

├── go.mod
├── go.sum
├── main.go
├── plugin
│   ├── go.mod
│   ├── go.sum
│   ├── myplugin.so
│   └── vendor
└── vendor
    ├── golang.org
    └── modules.txt

plugin/myplugin.go:

package main

import (
	"fmt"

	_ "golang.org/x/xerrors"
)

var ExportedVariable int = 42

func ExportedFunction() {
	fmt.Println("Hello from the plugin!")
}

main.go:

package main

import (
	"fmt"
	"plugin"

	_ "golang.org/x/xerrors"
)

func main() {
	p, err := plugin.Open("plugin/myplugin.so")
	if err != nil {
		fmt.Println("Error opening plugin:", err)
		return
	}

	exportedVar, err := p.Lookup("ExportedVariable")
	if err != nil {
		fmt.Println("Error looking up variable:", err)
		return
	}

	varValue, ok := exportedVar.(*int)
	if !ok {
		fmt.Println("Error getting variable value")
		return
	}

	fmt.Println("Exported variable:", *varValue)

	exportedFunc, err := p.Lookup("ExportedFunction")
	if err != nil {
		fmt.Println("Error looking up function:", err)
		return
	}

	exportedFunc.(func())()
}

Build the plugin:

$ cd plugin
$ go build -buildmode=plugin -mod=vendor -o myplugin.so myplugin.go

Build the main program:

$ cd ..
$ go build -mod=vendor -o main main.go
$ ./main
Error opening plugin: plugin.Open("plugin/myplugin"): plugin was built with a different version of package golang.org/x/xerrors/internal
$ go version -m plugin/myplugin.so
plugin/myplugin.so: devel go1.22-5873bd1d7e Mon Oct 16 03:29:27 2023 +0000
        path    command-line-arguments
        dep     golang.org/x/xerrors    v0.0.0-20231012003039-104605ab7028      h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
        build   -buildmode=plugin
        build   -compiler=gc
        build   CGO_ENABLED=1
        build   CGO_CFLAGS=
        build   CGO_CPPFLAGS=
        build   CGO_CXXFLAGS=
        build   CGO_LDFLAGS=
        build   GOARCH=arm64
        build   GOOS=darwin
        
$ go version -m main
main: devel go1.22-5873bd1d7e Mon Oct 16 03:29:27 2023 +0000
        path    command-line-arguments
        dep     golang.org/x/xerrors    v0.0.0-20231012003039-104605ab7028      h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
        build   -buildmode=exe
        build   -compiler=gc
        build   CGO_ENABLED=1
        build   CGO_CFLAGS=
        build   CGO_CPPFLAGS=
        build   CGO_CXXFLAGS=
        build   CGO_LDFLAGS=
        build   GOARCH=arm64
        build   GOOS=darwin

It should tell me what the different version is so I can match it.

The root cause might be something else: the full file path, the build flags, ... not the package version. Moreover, I'm not sure if we can tell what the different versions are. I tried to make a change here:

diff --git a/src/runtime/plugin.go b/src/runtime/plugin.go
index 40dfefde17..33022c60f2 100644
--- a/src/runtime/plugin.go
+++ b/src/runtime/plugin.go
@@ -51,7 +51,7 @@ func plugin_lastmoduleinit() (path string, syms map[string]any, initTasks []*ini
        for _, pkghash := range md.pkghashes {
                if pkghash.linktimehash != *pkghash.runtimehash {
                        md.bad = true
-                       return "", nil, nil, "plugin was built with a different version of package " + pkghash.modulename
+                       return "", nil, nil, "plugin was built with a different version of package " + pkghash.modulename + ": got " + *pkghash.runtimehash + ", want " + pkghash.linktimehash
                }
        }

but what I got is something like this:

Error opening plugin: plugin.Open("plugin/myplugin"): plugin was built with a different version of package golang.org/x/xerrors/internal: got %uV�┌, ┬▒┼├ NWIꘓ├

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. help wanted NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
Development

No branches or pull requests

6 participants