I
I
Ilya Bondarenko2016-10-28 13:06:13
go
Ilya Bondarenko, 2016-10-28 13:06:13

Why doesn't the lock work with sync.Mutex?

There is the following code:

type rawCatalogArray struct {
  sync.Mutex
  TagArray []RawCatalogTag   `xml:",any"`
  TagMap   map[string]string `xml:"-"`
}

func (a *rawCatalogArray) GetKeyValue(key string) (value string, e error) {
  a.Lock()
  defer a.Unlock()
  var exist bool
  value, exist = a.TagMap[key]
  if exist {
    return
  }
  e = catErrors.New("\"%s\" is not a valid tag.", key)
  return
}

Which is performed by the north. When testing with `go test` and running a single request, everything works great! But when processing parallel requests, the server crashes:
fatal error: concurrent map read and map write
goroutine 81 [running]:
runtime.throw(0x93a23d, 0x21)
/usr/local/Cellar/go/1.7.3/libexec/src/runtime/panic.go:566 +0x95 fp 0xc4203dd138 = sp = 0xc4203dd118
runtime.mapaccess2_faststr (0x84e260, 0xc42021a300, 0x9291be, 0xc, 0xc42006b768, 0xa)
/usr/local/Cellar/go/1.7.3/libexec/src/runtime/hashmap_fast.go:306 + fp = 0x76e 0xc4203dd1d0 sp=0xc4203dd138
store/catalog.(*rawCatalogArray).GetKeyValue(0xc42006b768, 0x9291be, 0xc, 0x0, 0x0, 0x0, 0x0)
/Users/ibondarenko/Projects/Go/store/src/store/catalog/raw.go:298 +0x154 fp=0xc4203dd258 sp=0xc4203dd1d0
store/catalog.(*ClientV3Config).SetRotateTimer(0xc4203dd3b0, 0xc42006b700)
/Users/ibondarenko/Projects/Go/store/src/store/catalog/client_v3.go:113 +0x58 fp=0xc4203dd2a8 sp=0xc4203dd258
store/catalog.(*ClientV3).SetConfig(0xc4203dd2f8, 0xc42006b700)
/Users/ibondarenko/ Projects / Go / store / src / store / catalog / client_v3.go: 85 0xe5 fp = + sp = 0xc4203dd2d0 0xc4203dd2a8
store / catalog.NewClientV3 (0xc42006b700, 0xc4200ab130, 0x4b, 0xc4200ab1d0, 0x4e, 0xc42013ec98, 0x7, 0xc42013ecc8, 0x7, 0xc42013ecf8 , ...)
/Users/ibondarenko/Projects/Go/store/src/store/catalog/client_v3.go:73 +0x96 fp=0xc4203dd2f0 sp=0xc4203dd2d0
store/responders.(*Client).ProcessV3(0xc4203dd958, 0xc42006b700)
/Users/ibondarenko/Projects/Go/store/src/store/responders/client.go:262 +0x54 fp=0xc4203dd800 sp=0xc4203dd2f0
main.httpHandler(0xcdea80, 0xc4201e6ea0, 0xc420206ff0)
/Users/ibondarenko/Projects/Go/store/src/store/client.go:96 +0x363 fp=0xc4203ddb98 sp=0xc4203dd800
main.(*Bootstrap).ServeHTTP(0xd21ec98, , 0xc4201e6ea0, 0xc420206ff0)
/Users/ibondarenko/Projects/Go/store/src/store/client.go:40 0x3ab + fp = 0xc4203ddc08 sp = 0xc4203ddb98
net / http.serverHandler.ServeHTTP (0xc4201e0800, 0xcdea80, 0xc4201e6ea0, 0xc420206ff0)
/ usr/local/Cellar/go/1.7.3/libexec/src/net/http/server.go:2202 +0xbc fp=0xc4203ddc50 sp=0xc4203ddc08
net/http.(*conn).serve(0xc4202f0f00, 0xcdf440, 0xc4203e42c0)
/usr/local/Cellar/go/1.7.3/libexec/src/net/http/server.go:1579 +0x5f7 fp=0xc4203ddf88 sp=0xc4203ddc50
runtime.goexit()
/usr/local/Cellar/go/1.7.3/libexec/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc4203ddf90 sp=0xc4203ddf88
created by net/http.(*Server).Serve
/usr/local/Cellar /go/1.7.3/libexec/src/net/http/server.go:2293 +0x541

I'm new to Go, the project is old, I'm trying to figure it out. Why is the code executed before reading from the dictionary if the mutex is locked? Tell me where to dig.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
I
Ilya, 2016-10-28
@FireGM

Because use RWMutex
At you somewhere it is written in TagMap without use of a mutex.

B
bnytiki, 2016-10-28
@bnytiki

The lock should work fine.
Put before and after a.Lock()
log.Printf("Call a.Lock(). Before")
and
log.Printf("Call a.Lock(). After")
and make sure.
This code should not compile at all.
Did you provide the complete code?

E
Evgeniy Ivakha, 2016-11-03
@ivahaev

In the stack trace, in principle, it is written where the previous call to the map was made. It's worth taking a look there. Definitely someone else is working with the map.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question