Go version
go1.24.0
Output of go env
in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/aryank.upadhyay@zomato.com/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/aryank.upadhyay@zomato.com/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/xm/5fwwh80x6vz1xgft05lyp3800000gn/T/go-build1603238070=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Users/aryank.upadhyay@zomato.com/go/src/github.com/Zomato/search-service/go.mod'
GOMODCACHE='/Users/aryank.upadhyay@zomato.com/go/pkg/mod'
GONOPROXY='github.com/Zomato/*'
GONOSUMDB='github.com/Zomato/*'
GOOS='darwin'
GOPATH='/Users/aryank.upadhyay@zomato.com/go'
GOPRIVATE='github.com/Zomato/*'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/Users/aryank.upadhyay@zomato.com/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.0.darwin-arm64'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/aryank.upadhyay@zomato.com/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/Users/aryank.upadhyay@zomato.com/go/pkg/mod/golang.org/toolchain@v0.0.1-go1.24.0.darwin-arm64/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.24.0'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
We are iterating over the docs through function GetFieldToDocsMap
.
Share below the piece of code
type Document struct {
Doc map[string]interface{}
mux sync.RWMutex `json:"-" msgpack:"-" snappy:"-"`
}
func GetFieldToDocsMap(fieldName string, docs []*Document) map[int]*Document {
resToDocMap := make(map[int]*index.Document)
for i := range docs {
id, ok := Int(docs[i].Get(fieldName))
if !ok {
continue
}
resToDocMap[id] = docs[i]
}
return resToDocMap
}
func (d *Document) Set(k string, v interface{}) {
if d == nil {
return
}
d.mux.Lock()
defer d.mux.Unlock()
d.Doc[k] = v
}
func (d *Document) Get(k string) (v interface{}) {
if d == nil {
return
}
d.mux.RLock()
defer d.mux.RUnlock()
v = d.Doc[k]
return v
}
We are using the using the docs multiple times in same request with proper synchronisation. also the function GetFieldToDocsMap is used in various go-routines.
docsMap := GetFieldToDocsMap("ID", Response.ModifiedResult.Results.Docs)
type IndexResult struct {
Status int
Results *Collection
}
type Collection struct {
Docs []*Document
Start int
NumFound int
}
type Response struct {
ModifiedResult *IndexResult
AlphaResult *IndexResult
StausValue bool
....
}
What did you see happen?
unexpected fault address 0x37303037313132
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0x37303037313132 pc=0x1b3b0]
goroutine 97106282 gp=0x415e9761c0 m=2 mp=0x4000108808 [running]:
runtime.throw({0x44abf46?, 0xeeb624?})
/usr/local/go/src/runtime/panic.go:1096 +0x38 fp=0x4250f16880 sp=0x4250f16850 pc=0x9e818
runtime.sigpanic()
/usr/local/go/src/runtime/signal_unix.go:939 +0x224 fp=0x4250f168e0 sp=0x4250f16880 pc=0xa15f4
internal/runtime/maps.(*Map).Used(...)
/usr/local/go/src/internal/runtime/maps/map.go:389
runtime.mapaccess1_faststr(0x39d7ac0?, 0x422cd05e00?, {0x44b70cf?, 0xeef930?})
/usr/local/go/src/internal/runtime/maps/runtime_faststr_swiss.go:110 +0x20 fp=0x4250f16970 sp=0x4250f168f0 pc=0x1b3b0
github.com/Zomato/search-service/internal/index.(*Document).Get(0x39e3b20?, {0x44b70cf?, 0x149c6b5?})
/go/src/github.com/Zomato/search-service/internal/index/response.go:279
goroutine 2 gp=0x4000002700 m=nil [force gc (idle), 513 minutes]:
runtime.gopark(...)
/usr/local/go/src/runtime/proc.go:435
runtime.goparkunlock(0x0?, 0x0?, 0x0?, 0x0?)
/usr/local/go/src/runtime/proc.go:441 +0xd0 fp=0x4000104fa0 sp=0x4000104f80 pc=0x5e4c0
runtime.forcegchelper()
/usr/local/go/src/runtime/proc.go:348 +0xac fp=0x4000104fd0 sp=0x4000104fa0 pc=0x5e31c
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4000104fd0 sp=0x4000104fd0 pc=0xa81f4
created by runtime.init.7 in goroutine 1
/usr/local/go/src/runtime/proc.go:336 +0x24
goroutine 3 gp=0x4000002c40 m=nil [GC sweep wait]:
runtime.gopark(...)
/usr/local/go/src/runtime/proc.go:435
runtime.goparkunlock(0x85efb01?, 0x0?, 0x44?, 0x0?)
/usr/local/go/src/runtime/proc.go:441 +0xd0 fp=0x4000105730 sp=0x4000105710 pc=0x5e4c0
runtime.bgsweep(0x4000122000)
/usr/local/go/src/runtime/mgcsweep.go:316 +0xf0 fp=0x40001057b0 sp=0x4000105730 pc=0x41640
runtime.gcenable.gowrap1()
/usr/local/go/src/runtime/mgc.go:204 +0x28 fp=0x40001057d0 sp=0x40001057b0 pc=0x33db8
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x40001057d0 sp=0x40001057d0 pc=0xa81f4
created by runtime.gcenable in goroutine 1
/usr/local/go/src/runtime/mgc.go:204 +0x6c
goroutine 4 gp=0x4000002e00 m=nil [GC scavenge wait]:
runtime.gopark(...)
/usr/local/go/src/runtime/proc.go:435
runtime.goparkunlock(0x4e3984?, 0x1f?, 0xff?, 0x0?)
/usr/local/go/src/runtime/proc.go:441 +0xd0 fp=0x4000105f60 sp=0x4000105f40 pc=0x5e4c0
runtime.(*scavengerState).park(0x85dee20)
/usr/local/go/src/runtime/mgcscavenge.go:425 +0x50 fp=0x4000105f90 sp=0x4000105f60 pc=0x3ed40
runtime.bgscavenge(0x4000122000)
/usr/local/go/src/runtime/mgcscavenge.go:658 +0xac fp=0x4000105fb0 sp=0x4000105f90 pc=0x3f2cc
runtime.gcenable.gowrap2()
/usr/local/go/src/runtime/mgc.go:205 +0x28 fp=0x4000105fd0 sp=0x4000105fb0 pc=0x33d58
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4000105fd0 sp=0x4000105fd0 pc=0xa81f4
created by runtime.gcenable in goroutine 1
/usr/local/go/src/runtime/mgc.go:205 +0xac
goroutine 17 gp=0x4000238000 m=nil [finalizer wait]:
runtime.gopark(0x0?, 0x424dc15b18?, 0xc0?, 0x51?, 0x1000000010?)
/usr/local/go/src/runtime/proc.go:435 +0xc8 fp=0x4008233d90 sp=0x4008233d70 pc=0x9e938
runtime.runfinq()
/usr/local/go/src/runtime/mfinal.go:196 +0x108 fp=0x4008233fd0 sp=0x4008233d90 pc=0x32e08
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4008233fd0 sp=0x4008233fd0 pc=0xa81f4
created by runtime.createfing in goroutine 1
/usr/local/go/src/runtime/mfinal.go:166 +0x80
goroutine 18 gp=0x40004508c0 m=nil [GC worker (idle)]:
runtime.gopark(0x1c1215e42557?, 0x3?, 0x8f?, 0xa3?, 0x0?)
/usr/local/go/src/runtime/proc.go:435 +0xc8 fp=0x40087caf10 sp=0x40087caef0 pc=0x9e938
runtime.gcBgMarkWorker(0x40002020e0)
/usr/local/go/src/runtime/mgc.go:1423 +0xdc fp=0x40087cafb0 sp=0x40087caf10 pc=0x3642c
runtime.gcBgMarkStartWorkers.gowrap1()
/usr/local/go/src/runtime/mgc.go:1339 +0x28 fp=0x40087cafd0 sp=0x40087cafb0 pc=0x36318
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x40087cafd0 sp=0x40087cafd0 pc=0xa81f4
created by runtime.gcBgMarkStartWorkers in goroutine 1
/usr/local/go/src/runtime/mgc.go:1339 +0x140
goroutine 33 gp=0x4000182380 m=nil [GC worker (idle)]:
runtime.gopark(0x1c110bb368cb?, 0x3?, 0xa9?, 0xdf?, 0x0?)
/usr/local/go/src/runtime/proc.go:435 +0xc8 fp=0x4004080f10 sp=0x4004080ef0 pc=0x9e938
runtime.gcBgMarkWorker(0x40002020e0)
/usr/local/go/src/runtime/mgc.go:1423 +0xdc fp=0x4004080fb0 sp=0x4004080f10 pc=0x3642c
runtime.gcBgMarkStartWorkers.gowrap1()
/usr/local/go/src/runtime/mgc.go:1339 +0x28 fp=0x4004080fd0 sp=0x4004080fb0 pc=0x36318
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4004080fd0 sp=0x4004080fd0 pc=0xa81f4
created by runtime.gcBgMarkStartWorkers in goroutine 1
/usr/local/go/src/runtime/mgc.go:1339 +0x140
goroutine 5 gp=0x40000036c0 m=nil [GC worker (idle), 262 minutes]:
runtime.gopark(0xdbf6f0a523c?, 0x3?, 0x92?, 0x6b?, 0x0?)
/usr/local/go/src/runtime/proc.go:435 +0xc8 fp=0x40de956f10 sp=0x40de956ef0 pc=0x9e938
runtime.gcBgMarkWorker(0x40002020e0)
/usr/local/go/src/runtime/mgc.go:1423 +0xdc fp=0x40de956fb0 sp=0x40de956f10 pc=0x3642c
runtime.gcBgMarkStartWorkers.gowrap1()
/usr/local/go/src/runtime/mgc.go:1339 +0x28 fp=0x40de956fd0 sp=0x40de956fb0 pc=0x36318
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x40de956fd0 sp=0x40de956fd0 pc=0xa81f4
created by runtime.gcBgMarkStartWorkers in goroutine 1
/usr/local/go/src/runtime/mgc.go:1339 +0x140
goroutine 6 gp=0x4000003880 m=nil [GC worker (idle)]:
runtime.gopark(0x1c1215e52396?, 0x3?, 0xbb?, 0xdf?, 0x0?)
/usr/local/go/src/runtime/proc.go:435 +0xc8 fp=0x4006feef10 sp=0x4006feeef0 pc=0x9e938
runtime.gcBgMarkWorker(0x40002020e0)
/usr/local/go/src/runtime/mgc.go:1423 +0xdc fp=0x4006feefb0 sp=0x4006feef10 pc=0x3642c
runtime.gcBgMarkStartWorkers.gowrap1()
/usr/local/go/src/runtime/mgc.go:1339 +0x28 fp=0x4006feefd0 sp=0x4006feefb0 pc=0x36318
runtime.goexit({})
/usr/local/go/src/runtime/asm_arm64.s:1223 +0x4 fp=0x4006feefd0 sp=0x4006feefd0 pc=0xa81f4
created by runtime.gcBgMarkStartWorkers in goroutine 1
/usr/local/go/src/runtime/mgc.go:1339 +0x140
What did you expect to see?
Expectation: go build never crashes
Currently it seems like the fatal error is caused due to corrupt address. But in our code flow we are never directly updating the Document value. We use the Set method { shared the implementation above }
Here is piece of code which produces almost same stack trace:
func main() {
// A valid map
x := map[string]int{"foo": 42}
// Create a pointer to the map
y := &x
// Now override the address of y with a pointer to a string
s := "7007112" // corrupt memory: these bytes will become the map header
ptrToY := (*unsafe.Pointer)(unsafe.Pointer(&y))
stringPtr := *(*unsafe.Pointer)(unsafe.Pointer(&s))
*ptrToY = stringPtr
// Force a runtime access to the corrupted map — triggers SIGSEGV
fmt.Println((*y)["someKey"])
}
Comment From: adonovan
Are you able to reproduce the problem? If so, have you tried using the -race flag to eliminate the possibility of a data race? (Though your locking does look sound.)
@prattmic
Comment From: prattmic
The fault address 0x37303037313132 looks an awful lot like ASCII data, so a race condition or other unsafe misuse seems likely to me. Note that string
is struct{ data unsafe.Pointer; len int }
, so if Document
were overwritten by a string value then the map pointer becomes the pointer to the string contents.