aboutsummaryrefslogtreecommitdiff
path: root/src/plugin
diff options
context:
space:
mode:
authorDavid Crawshaw <crawshaw@golang.org>2017-09-02 12:05:35 -0400
committerDavid Crawshaw <crawshaw@golang.org>2017-09-09 16:26:33 +0000
commitd8ae2156fe08f31f9b20a79b6971638c5bf203b5 (patch)
tree3619d960bfd11ddf4ea45fc60f6c30048f8bab55 /src/plugin
parent4e2ef7f7f9a3351c3774148c40fe0d7f12403da5 (diff)
downloadgo-d8ae2156fe08f31f9b20a79b6971638c5bf203b5.tar.gz
go-d8ae2156fe08f31f9b20a79b6971638c5bf203b5.zip
runtime, plugin: error not throw on duplicate open
Along the way, track bad modules. Make sure they don't end up on the active modules list, and aren't accidentally reprocessed as new plugins. Fixes #19004 Change-Id: I8a5e7bb11f572f7b657a97d521a7f84822a35c07 Reviewed-on: https://go-review.googlesource.com/61171 Run-TryBot: David Crawshaw <crawshaw@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/plugin')
-rw-r--r--src/plugin/plugin.go1
-rw-r--r--src/plugin/plugin_dlopen.go26
2 files changed, 17 insertions, 10 deletions
diff --git a/src/plugin/plugin.go b/src/plugin/plugin.go
index c774465812..c37b65fd82 100644
--- a/src/plugin/plugin.go
+++ b/src/plugin/plugin.go
@@ -20,6 +20,7 @@ package plugin
// Plugin is a loaded Go plugin.
type Plugin struct {
pluginpath string
+ err string // set if plugin failed to load
loaded chan struct{} // closed when loaded
syms map[string]interface{}
}
diff --git a/src/plugin/plugin_dlopen.go b/src/plugin/plugin_dlopen.go
index ce66c036c9..37380989d7 100644
--- a/src/plugin/plugin_dlopen.go
+++ b/src/plugin/plugin_dlopen.go
@@ -87,7 +87,7 @@ func open(name string) (*Plugin, error) {
if C.realpath(
(*C.char)(unsafe.Pointer(&cRelName[0])),
(*C.char)(unsafe.Pointer(&cPath[0]))) == nil {
- return nil, errors.New("plugin.Open(" + name + "): realpath failed")
+ return nil, errors.New(`plugin.Open("` + name + `"): realpath failed`)
}
filepath := C.GoString((*C.char)(unsafe.Pointer(&cPath[0])))
@@ -95,6 +95,9 @@ func open(name string) (*Plugin, error) {
pluginsMu.Lock()
if p := plugins[filepath]; p != nil {
pluginsMu.Unlock()
+ if p.err != "" {
+ return nil, errors.New(`plugin.Open("` + name + `"): ` + p.err + ` (previous failure)`)
+ }
<-p.loaded
return p, nil
}
@@ -102,22 +105,25 @@ func open(name string) (*Plugin, error) {
h := C.pluginOpen((*C.char)(unsafe.Pointer(&cPath[0])), &cErr)
if h == 0 {
pluginsMu.Unlock()
- return nil, errors.New("plugin.Open: " + C.GoString(cErr))
+ return nil, errors.New(`plugin.Open("` + name + `"): ` + C.GoString(cErr))
}
// TODO(crawshaw): look for plugin note, confirm it is a Go plugin
// and it was built with the correct toolchain.
if len(name) > 3 && name[len(name)-3:] == ".so" {
name = name[:len(name)-3]
}
-
- pluginpath, syms, mismatchpkg := lastmoduleinit()
- if mismatchpkg != "" {
- pluginsMu.Unlock()
- return nil, errors.New("plugin.Open: plugin was built with a different version of package " + mismatchpkg)
- }
if plugins == nil {
plugins = make(map[string]*Plugin)
}
+ pluginpath, syms, errstr := lastmoduleinit()
+ if errstr != "" {
+ plugins[filepath] = &Plugin{
+ pluginpath: pluginpath,
+ err: errstr,
+ }
+ pluginsMu.Unlock()
+ return nil, errors.New(`plugin.Open("` + name + `"): ` + errstr)
+ }
// This function can be called from the init function of a plugin.
// Drop a placeholder in the map so subsequent opens can wait on it.
p := &Plugin{
@@ -153,7 +159,7 @@ func open(name string) (*Plugin, error) {
p := C.pluginLookup(h, (*C.char)(unsafe.Pointer(&cname[0])), &cErr)
if p == nil {
- return nil, errors.New("plugin.Open: could not find symbol " + symName + ": " + C.GoString(cErr))
+ return nil, errors.New(`plugin.Open("` + name + `"): could not find symbol ` + symName + `: ` + C.GoString(cErr))
}
valp := (*[2]unsafe.Pointer)(unsafe.Pointer(&sym))
if isFunc {
@@ -184,4 +190,4 @@ var (
)
// lastmoduleinit is defined in package runtime
-func lastmoduleinit() (pluginpath string, syms map[string]interface{}, mismatchpkg string)
+func lastmoduleinit() (pluginpath string, syms map[string]interface{}, errstr string)