-
Notifications
You must be signed in to change notification settings - Fork 18.5k
Description
What version of Go are you using (go version)?
$ go version go version go1.13.7 darwin/amd64 $ uname -a Darwin newbmiaodeMacBook-Pro.local 17.7.0 Darwin Kernel Version 17.7.0: Sun Jun 2 20:31:42 PDT 2019; root:xnu-4570.71.46~1/RELEASE_X86_64 x86_64
Does this issue reproduce with the latest release?
Not sure
What operating system and processor architecture are you using (go env)?
go env Output
$ go env GO111MODULE="" GOARCH="amd64" GOBIN="" GOCACHE="/Users/newbmiao/Library/Caches/go-build" GOENV="/Users/newbmiao/Library/Application Support/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/newbmiao/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/Cellar/go/1.13.7/libexec" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/Cellar/go/1.13.7/libexec/pkg/tool/darwin_amd64" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/m_/hlhv5wl17vg368420bbxszhc0000gn/T/go-build908799930=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
This issue about test the spec below, but got panic:
https://golang.org/pkg/sync/atomic/#pkg-note-BUG
The first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned.
I use code below to test, and will panic occasionally
(Test it on my 64-bit mac: GOARCH=386 go build -ldflags=-compressdwarf=false -o test test.go)
But if i remove the fmt.Println() inside of the test function, it will pass.
I also debug it use gdb (append info below), x escape to heap, and use tinyallocs to alloc it
And i notice thatc.tinyoffset is 2.
But when no fmt.Println() it will be 0 or 16, Or just nextFreeFast to get a new object.
So i am confused, is that spec work in this situation?
Or maybe i misunderstand with this spec?
Or a issue cross compile under macOS?
May related with this issue: #599
Code:
package main
import (
"fmt"
"sync/atomic"
)
// On ARM, x86-32, and 32-bit MIPS, it is the caller's responsibility to arrange for 64-bit alignment of 64-bit words accessed atomically.
// The first word in a variable or in an allocated struct, array, or slice can be relied upon to be 64-bit aligned.
func test(){
x := struct {
v uint64
y uint32
}{}
fmt.Println() //if comment this line, it will pass on 32-bit arch
atomic.AddUint64(&x.v, 1)
}
func main() {
test()
}gdb info
$ GOARCH=386 go build -ldflags=-compressdwarf=false -o test test.go
$ gdb ./hello
(gdb) b main.main
Thread 2 hit Breakpoint 1, main.main ()
at /Dig101-Go/test.go:19
19 func main() {
(gdb) s
20 test()
(gdb)
main.test () at /Dig101-Go/test.go:10
10 func test(){
(gdb)
11 x := struct {
(gdb)
runtime.newobject (typ=0x9d280 <type.*+93280>, ~r1=<optimized out>)
at /usr/local/Cellar/go/1.13.7/libexec/src/runtime/malloc.go:1150
1150 func newobject(typ *_type) unsafe.Pointer {
(gdb)
1151 return mallocgc(typ.size, typ, true)
(gdb)
runtime.mallocgc (size=<optimized out>, typ=0x9d280 <type.*+93280>, needzero=true,
~r3=<optimized out>)
at /usr/local/Cellar/go/1.13.7/libexec/src/runtime/malloc.go:877
877 func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
(gdb)
878 if gcphase == _GCmarktermination {
(gdb) until 945
runtime.mallocgc (size=<optimized out>, typ=0x9d280 <type.*+93280>, needzero=true, ~r3=<optimized out>)
at /usr/local/Cellar/go/1.13.7/libexec/src/runtime/malloc.go:945
945 if size <= maxSmallSize {
(gdb) n
946 if noscan && size < maxTinySize {
(gdb)
976 off := c.tinyoffset
(gdb)
978 if size&7 == 0 {
(gdb)
980 } else if size&3 == 0 {
(gdb)
981 off = round(off, 4)
(gdb)
985 if off+size <= maxTinySize && c.tiny != 0 {
(gdb) p off
$1 = 4
(gdb) p c.tinyoffset <========= notice this line
$2 = 2
(gdb) n
987 x = unsafe.Pointer(c.tiny + off)
(gdb)
988 c.tinyoffset = off + size
(gdb)
989 c.local_tinyallocs++
(gdb)
990 mp.mallocing = 0
(gdb)
991 releasem(mp)
(gdb)
992 return x
(gdb)
main.test () at /Dig101-Go/test.go:16
16 fmt.Println()
(gdb)
17 atomic.AddUint64(&x.v, 1)
(gdb)
Thread 2 received signal SIGSEGV, Segmentation fault.
runtime/internal/atomic.Xadd64 () at /usr/local/Cellar/go/1.13.7/libexec/src/runtime/internal/atomic/asm_386.s:105
105 MOVL 0, AX // crash when unaligned
(gdb)
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x2f7c]
goroutine 1 [running]:
runtime/internal/atomic.Xadd64(0x1141c0b4, 0x1, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.13.7/libexec/src/runtime/internal/atomic/asm_386.s:105 +0xc
main.test()
/Dig101-Go/test.go:17 +0x72
main.main()
/Dig101-Go/test.go:20 +0x11
[Inferior 1 (process 68214) exited with code 02]What did you expect to see?
go run successfully
What did you see instead?
Panic sometimes:
$ ./test # success
$ ./test # failed
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x2f7c]
goroutine 1 [running]:
runtime/internal/atomic.Xadd64(0x1147e004, 0x1, 0x0, 0x0, 0x0)
/usr/local/Cellar/go/1.13.7/libexec/src/runtime/internal/atomic/asm_386.s:105 +0xc
main.test()
/Dig101-Go/test.go:17 +0x72
main.main()
/Dig101-Go/test.go:20 +0x11