Задать вопрос
@rail01y

Из-за чего возникает ошибка fatal error: concurrent map writes?

Доброго времени суток!

Не могли бы пожалуйста подсказать, где я допустил ошибку, что временами go выкидывает ошибку
fatal error: concurrent map writes


Код:
func GetDocumentFrontend(filter bson.M, isPreview bool) (doc *Document, err error) {
	doc = &Document{}

	filter["deleted"] = false
	filter["published"] = true
	list, err := documentAggregateSearch(filter, 1, 0, "", BasicRelationsListing)
	if err != nil {
		return
	}
	if len(list) == 0 {
		return nil, fmt.Errorf("No documents found")
	}

	js, _ := json.Marshal(list[0])
	if err = json.Unmarshal(js, &doc); err != nil {
		return
	}

	return
}


Трейс ошибки:
Jan 10 20:58:31 app sh: fatal error: concurrent map writes
Jan 10 20:58:31 app sh: goroutine 252807 [running]:
Jan 10 20:58:31 app sh: runtime.throw(0x7f427f494f2c, 0x15)
Jan 10 20:58:31 app sh: /usr/local/go/src/runtime/panic.go:617 +0x74 fp=0xc00057f210 sp=0xc00057f1e0 pc=0x7f427edd5534
Jan 10 20:58:31 app sh: runtime.mapassign_faststr(0xefd800, 0xc000465350, 0x7f427f48ca9f, 0x7, 0xc000040700)
Jan 10 20:58:31 app sh: /usr/local/go/src/runtime/map_faststr.go:211 +0x438 fp=0xc00057f278 sp=0xc00057f210 pc=0x7f427edbc7a8
Jan 10 20:58:31 app sh: app/core/models/documents.GetDocumentFrontend(0xc000465350, 0xc000465301, 0xc000458774, 0x4, 0xc000457cb8)
Jan 10 20:58:31 app sh: /home/gitlab-runner/builds/BMuFqxHZ/0/auth/app/core/models/documents/service.go:302 +0xc1 fp=0xc00057f310 sp=0xc00057f278 pc=0x7f427f3a5691
Jan 10 20:58:31 app sh: plugin/unnamed-787bb3a7aa138abb2aa6eca860b2ab7eca546b81.SiteController(0x7f42955418a0, 0xc00010e0b0, 0xc000ce8a00)
Jan 10 20:58:31 app sh: /home/gitlab-runner/builds/BMuFqxHZ/0/auth/app/frontend/main/controllers/SiteController.go:93 +0x539 fp=0xc00057f500 sp=0xc00057f310 pc=0x7f427f487419
Jan 10 20:58:31 app sh: github.com/urfave/negroni.WrapFunc.func1(0x7f42955418a0, 0xc00010e0b0, 0xc000ce8a00, 0xc000352280


собственно насколько я понимаю он вылетает на строчке: app/core/models/documents/service.go:302, которая в функции выше является следующей:

filter["deleted"] = false
)
  • Вопрос задан
  • 3358 просмотров
Подписаться 1 Простой Комментировать
Пригласить эксперта
Ответы на вопрос 2
Эта ошибка возникает потому что вы из двух горутин одновременно пишете в одну мапу. Так нельзя, ибо map не потокобезопасен. Конкурентный доступ к ней надо защищать мьютексом.
Или можете использовать sync.Map, который появился в go 1.9, там это сделали за вас.
Ответ написан
uvelichitel
@uvelichitel Куратор тега Go
habrahabr.ru/users/uvelichitel
bson.M это map, это ссылочный тип. Когда вы передаете map аргументом в функцию вы передаете ссылку на участок памяти. Соответственно при конкурентном доступе к этому участку и возникает ошибка. Вам следует либо защитить этот участок примитивами синхронизации вроде sync.Mutex либо передавать в функцию не map, а копию. Например (в коде из вашего комментария)
func SiteController(w http.ResponseWriter, r *http.Request) {
    bsonQuery := bson.M{}
    if node.Params.ExtendFilter != nil { //node.Params.ExtendFilter глобальная переменная
    //следует не просто взять ссылку на нее
    //bsonQuery = node.Params.ExtendFilter
    //а сделать копию для безопасного конкурентного использования
        for key, value := range  node.Params.ExtendFilter{
              bsonQuery[key] = value
        }
    }
    ....
   doc, err := documents.GetDocumentFrontend(bsonQuery, true)
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы