go: cmd/link: segfault with statically linked binaries on linux
Discovered with @tschottdorf.
package main
import (
"net"
"os/user"
"C"
)
func main() {
for i := 0; i < 1000; i++ {
_, _ = net.Dial("tcp", "localhost:1337")
_, _ = user.Current()
}
}
Note the “C” import is required, otherwise the go tool does not build a real static binary.
$ go run -ldflags '-extldflags "-static"' main.go
fatal error: unexpected signal during runtime execution
[signal 0xb code=0x1 addr=0xe5 pc=0x7fec267f8a5c]
runtime stack:
runtime.throw(0x660380, 0x2a)
/usr/local/go/src/runtime/panic.go:527 +0x90
runtime.sigpanic()
/usr/local/go/src/runtime/sigpanic_unix.go:12 +0x5a
goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x402620, 0xc82004bd30, 0xc800000000)
/usr/local/go/src/runtime/cgocall.go:120 +0x11b fp=0xc82004bce0 sp=0xc82004bcb0
os/user._Cfunc_mygetpwuid_r(0x0, 0xc8200172c0, 0x7fec180008c0, 0x400, 0xc82002a0b0, 0x0)
??:0 +0x39 fp=0xc82004bd30 sp=0xc82004bce0
os/user.lookupUnix(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/os/user/lookup_unix.go:99 +0x723 fp=0xc82004bea0 sp=0xc82004bd30
os/user.current(0x0, 0x0, 0x0)
/usr/local/go/src/os/user/lookup_unix.go:39 +0x42 fp=0xc82004bee0 sp=0xc82004bea0
os/user.Current(0x62eba8, 0x0, 0x0)
/usr/local/go/src/os/user/lookup.go:9 +0x24 fp=0xc82004bf00 sp=0xc82004bee0
main.main()
/go/src/github.com/cockroachdb/cgo_static_boom/main.go:13 +0x55 fp=0xc82004bf50 sp=0xc82004bf00
runtime.main()
/usr/local/go/src/runtime/proc.go:111 +0x2b0 fp=0xc82004bfa0 sp=0xc82004bf50
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1696 +0x1 fp=0xc82004bfa8 sp=0xc82004bfa0
goroutine 17 [syscall, locked to thread]:
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1696 +0x1
exit status 2
This was discovered in a docker image based on golang:1.5.1, but also tested against go1.5.2
and 606d9a7e (tip at the time of writing), both built from source in the container. The segfault reproduces in all three. The docker image was running in a virtualbox VM.
Output of go env
:
$ go env
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT=""
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="g++"
CGO_ENABLED="1"
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 26 (13 by maintainers)
Commits related to this issue
- runtime/internal: Avoid use of os/user to generate default blessing names. The user of os/user causes trouble with statically linked binaries (see https://github.com/golang/go/issues/13470 and https:... — committed to vanadium-archive/go.ref by asimshankar 8 years ago
- google: prefer os.Getenv("HOME") over os/user.Current() so as to avoid SEGV Due to an issue in handling thread-local storages, os/user can lead to SEGV when glibc is statically linked with. So we pr... — committed to golang/oauth2 by AkihiroSuda 8 years ago
- gcplogs: forcibly set HOME on static UNIX binary Fix #29344 If HOME is not set, the gcplogs logging driver will call os/user.Current() via oauth2/google. However, in static binary, os/user.Current()... — committed to AkihiroSuda/docker by AkihiroSuda 8 years ago
- Build static binary with Go internal linker Static linking with gcc may cause segfaults at runtime on some systems (see https://github.com/golang/go/issues/13470) — committed to janeczku/external-dns by janeczku 7 years ago
- Build static binary with Go internal linker Static linking with gcc may cause segfaults at runtime on some systems (see https://github.com/golang/go/issues/13470) — committed to janeczku/external-dns by janeczku 7 years ago
- ttrpc: use os.Getuid/os.Getgid directly Because of issues with glibc, using the `os/user` package can cause when calling `user.Current()`. Neither the Go maintainers or glibc developers could be both... — committed to containerd/ttrpc by stevvooe 7 years ago
Here’s another way that people deal with this: https://github.com/tamird/cockroach/commit/9c93044ce7d3283e78f5941b8b9bcd836f80a7ef