Rodrigo.C
Rodrigo.C

Reputation: 1173

Unable to open a Go plugin

I always get the following error:

plugin.Open("./plugin"): plugin was built with a different version of package internal/cpu

I did some research about this issue, and it's clearly pointing out that the plugin has been built using different context versions (golang version, or dependencies) than the app loading the plugin.

I ran a minimal test under Docker, using exactly the same Go compiler version and same image to build both the plugin and the app, but I'm still getting the same error.

I appreciate if anyone can point me out where's the failure, or what else should I check to prevent this error.

It's worth mentioning I'm using MacOS, but I'm running the test under Docker containers. Actually, I was able to build and run golang plugins under Docker for third party products.

This is the code:

// main.go

package main

import (
    "fmt"
    "plugin"
)

func main() {
    path := "./plugin.so"
    p, err := plugin.Open(path)
    if err != nil {
        fmt.Printf("unable to load plugin at %s.\n%v", path, err)
    }

    symbol, err := p.Lookup("Create")
    if err != nil {
        fmt.Printf("unable to find Create() function in plugin %s.\n%v", path, err)
    }

    createMethod, ok := symbol.(func()interface{})
    if !ok {
        fmt.Printf("Create is not a function in plugin %s", path)
    }
    createMethod()
}
// plugin.go

package main

func Create() interface{} {
    return nil
}
//Dockerfile

FROM golang:1.13.5 as pluginBuilder

WORKDIR /app

COPY . .

RUN go build --buildmode=plugin --trimpath -o /plugin.so plugin.go

FROM golang:1.13.5 as serverBuilder
WORKDIR /app

COPY . .

RUN go build -o /server main.go

FROM debian:stable AS server

WORKDIR /app
COPY --from=pluginBuilder /plugin.so .
COPY --from=serverBuilder /server .

RUN /app/server

Thanks

Upvotes: 4

Views: 1594

Answers (1)

Brits
Brits

Reputation: 18380

You are using the -trimpath option when building the plugin but not when building the app. Edit the docker file so both builds use -trimpath (or neither do) then the application will run (well it does on my machine).

My guess as to why this causes the issue is that trimpath "removes all file system paths from the compiled executable" so when the runtime verifies versions it picks up the difference in the paths.

Here is the dockerfile that works for me (having replicated the issue with the original; the only change is adding -trimpath to the second go build):

FROM golang:1.13.5 as pluginBuilder

WORKDIR /app

COPY . .

RUN go build --buildmode=plugin --trimpath -o /plugin.so plugin.go

FROM golang:1.13.5 as serverBuilder
WORKDIR /app

COPY . .

RUN go build --trimpath -o /server main.go

FROM debian:stable AS server

WORKDIR /app
COPY --from=pluginBuilder /plugin.so .
COPY --from=serverBuilder /server .

RUN /app/server

Upvotes: 5

Related Questions