go: cmd/compile: escaping closure incorrectly allocated on the stack

Please answer these questions before submitting your issue. Thanks!

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

go version go1.7.1 darwin/amd64

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

GOARCH=“amd64” GOBIN=“” GOEXE=“” GOHOSTARCH=“amd64” GOHOSTOS=“darwin” GOOS=“darwin” GOPATH=“/Users/jacob/Projects/gocode” GORACE=“” GOROOT=“/usr/local/Cellar/go/1.7.1/libexec” GOTOOLDIR=“/usr/local/Cellar/go/1.7.1/libexec/pkg/tool/darwin_amd64” CC=“clang” GOGCCFLAGS=“-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/d6/ynnsnz1x4m9188yk1r8xns3w0000gn/T/go-build882056681=/tmp/go-build -gno-record-gcc-switches -fno-common” CXX=“clang++” CGO_ENABLED=“1”

Also tested with same configuration using GOARCH=386 on Darwin (issue reproducible) and on windows/386 in a virtual machine (issue NOT reproducible).

What did you do?

Attempted to pass a closure as a callback to another function that generates values to be processed and invokes the callback with these values (see demo below).

What did you expect to see?

The program should run without issue.

What did you see instead?

After an indeterminate number of invocations, the closure seems to be invalidated, and invoking it as a callback generates a segmentation fault. Alternatively, with optimizations disabled, the garbage collector indicates that there is a reference to an invalid block of memory (which to my novice reading seems to be pointing at the closure).

A package demonstrating this problem (and including stack traces) is available here:

https://github.com/havoc-io/go-closure-issue

I apologize in advance for not being able to produce a more minimal test case - I really did try. This package is already extracted from a larger program.

Instructions and more details are included in the repository, but cloning and running go test (possibly 3 or 4 times) should reproduce the error.

None of the code here uses unsafe or cgo, nor is the callback ever changed after defined. Using GOGC=off seems to stop the issue. Disabling SSA makes no difference. My suspicion is that the GC is somehow not realizing that the closure is referenced and is reclaiming it (potentially due to the complex structure of the function invoking the callback), but I am not even remotely an expert on Go’s internals or GC implementation.

Perhaps @kardianos can chime in since he wrote the underlying package.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 15 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Seems also like a Go1.7.x candidate to me @bradfitz / @drchase