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: json.Unmarshaler type assertion infinite loop from 1.8beta2 to 1.8rc1 #18676

Closed
fsenart opened this issue Jan 16, 2017 · 11 comments
Closed

Comments

@fsenart
Copy link

fsenart commented Jan 16, 2017

Please answer these questions before submitting your issue. Thanks!

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

go version go1.8rc1 linux/amd64

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

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/fsenart/exp"
GORACE=""
GOROOT="/home/fsenart/tools/exp"
GOTOOLDIR="/home/fsenart/tools/exp/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build256843014=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
PKG_CONFIG="pkg-config"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

// $GOPATH/src/issue/main.go

package main

import (
        "issue/dynamodbstreamsevt"
        "encoding/json"
        "plugin"
)

func main() {
        plugin.Open("plugin.so")

        var x interface{} = (*dynamodbstreamsevt.Event)(nil)
        if _, ok := x.(json.Unmarshaler); !ok {
                println("something")
        }
}
// $GOPATH/src/issue/plugin.go

package main

import "C"

import "issue/dynamodbstreamsevt"

func F(evt *dynamodbstreamsevt.Event) {}
// $GOPATH/src/issue/dynamodbstreamsevt/definition.go

package dynamodbstreamsevt

import "encoding/json"

var foo json.RawMessage

type Event struct{}

func (e *Event) Dummy() {}
test: build
        @./main

build: clean
        @go build -buildmode=plugin -o plugin.so plugin.go
        @go build -o main main.go

clean:
        @rm -rf main *.so

What did you expect to see?

The program should terminate.

What did you see instead?

The program goes into an infinite loop and does not terminate. If you see processor usage with top, you'll notice that the program uses 100% of one processor and never gives up.

Observations

If you change anything the program will terminate !!!

  • If you change the name dynamodbstreamsevt by anything else, all goes well and the program terminates.
  • If you change the name Event by anything else, all goes well and the program terminates.
  • If Event has not at least one method like Dummy, all goes well and the program terminates.
  • If encoding/json is not imported in the dynamodbstreamsevt package, all goes well and the program terminates.
  • If encoding/json is not used in plugin.so, all goes well and the program terminates.
  • If plugin feature is not used, all goes well and the program terminates.

I admit that what I'm saying here seems very very weird, but I even tested in a fresh machine without anything else than the above code and the name dynamodbstreamsevt and Event seem magic!

Above program terminates well with go1.8beta2, so I conclude that this is a regression in go1.8rc1.

@josharian
Copy link
Contributor

@crawshaw

@crawshaw
Copy link
Member

Quite the bug. Do you get a stack trace if you send a SIGQUIT? (Ctrl+\ on a typical terminal.)

@fsenart
Copy link
Author

fsenart commented Jan 16, 2017

^\SIGQUIT: quit
PC=0x47d65f m=0 sigcode=128

goroutine 1 [running]:
runtime.getitab(0x5320e0, 0x52fc20, 0x1, 0x0)
	/home/fsenart/tools/exp/src/runtime/iface.go:55 +0xcf fp=0xc42004df18 sp=0xc42004de80
runtime.assertE2I2(0x5320e0, 0x52fc20, 0x0, 0x0, 0x0, 0xc4200001a0)
	/home/fsenart/tools/exp/src/runtime/iface.go:294 +0x43 fp=0xc42004df48 sp=0xc42004df18
main.main()
	/home/fsenart/exp/src/issue/main.go:13 +0x5f fp=0xc42004df88 sp=0xc42004df48
runtime.main()
	/home/fsenart/tools/exp/src/runtime/proc.go:185 +0x20a fp=0xc42004dfe0 sp=0xc42004df88
runtime.goexit()
	/home/fsenart/tools/exp/src/runtime/asm_amd64.s:2197 +0x1 fp=0xc42004dfe8 sp=0xc42004dfe0

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
	/home/fsenart/tools/exp/src/runtime/asm_amd64.s:2197 +0x1

rax    0x0
rbx    0x52fc20
rcx    0x5320e0
rdx    0x7034bc00
rdi    0x7b90a0
rsi    0x111
rbp    0xc42004df08
rsp    0xc42004de80
r8     0x7c6520
r9     0x532160
r10    0xc420020050
r11    0x110
r12    0xc420098108
r13    0x1
r14    0x0
r15    0xc420098018
rip    0x47d65f
rflags 0x206
cs     0x33
fs     0x0
gs     0x0
Makefile:2: recipe for target 'test' failed
make: *** [test] Error 2

@crawshaw
Copy link
Member

Shot in the dark (I'm away from my linux machine until tomorrow), would you mind patching in https://golang.org/cl/35117?

@fsenart
Copy link
Author

fsenart commented Jan 16, 2017

@crawshaw I've just applied the patch and it works. Can you please provide a little explanation because I've lost a lot of hours and the patch is so tiny :)

@randall77
Copy link
Contributor

Yay! Figuring out a test for CL 35117 was on my plate for tomorrow. You've just done 90% of the work for me...

The explanation is that the itabs (pointers to which are the "type information" word of an interface) are put in linked lists in the runtime. If the same itab is inserted twice, it can lead to cycles in the linked lists. When a subsequent lookup operation happens on that linked list, it can run indefinitely.

@fsenart
Copy link
Author

fsenart commented Jan 17, 2017

@randall77 Okkkk. Thx for the explanation, the bug was so tricky for me to spot.
Can you confirm me that the patch will be applied for the next rc or final release, so that I can apply it in my docker image for now to unlock my issue lifadev/archive_aws-lambda-go-shim#2?

@randall77
Copy link
Contributor

Yes, it will be in the next rc.
(It will likely be submitted tomorrow.)

@randall77
Copy link
Contributor

@fsenart : Could you fill out a CLA so I can use your test code?
Follow the instructions at https://golang.org/doc/contribute.html#cla

@fsenart
Copy link
Author

fsenart commented Jan 17, 2017

Done ;)

@gopherbot
Copy link

CL https://golang.org/cl/35117 mentions this issue.

@golang golang locked and limited conversation to collaborators Jan 17, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants