Skip to content
This repository has been archived by the owner on Dec 8, 2022. It is now read-only.

fatal error: concurrent map writes #114

Closed
pioz opened this issue Jun 22, 2020 · 2 comments · Fixed by #169
Closed

fatal error: concurrent map writes #114

pioz opened this issue Jun 22, 2020 · 2 comments · Fixed by #169

Comments

@pioz
Copy link
Contributor

pioz commented Jun 22, 2020

I have a goroutine in a for loop that runs faker.FakeData, here a sample code:

package main

import (
	"reflect"
	"github.com/bxcodec/faker"
)

type User struct {
	Username string `faker:"first_name"`
	Email    string `faker:"email,unique"`
}

func main() {
	user := User{}
	modelType := reflect.TypeOf(user)
	for i := 0; i < 1000; i++ {
		go func() {
			for j := 0; j < 1000; j++ {
				modelCopy := reflect.New(modelType).Interface() // copy model
				faker.FakeData(modelCopy)
			}
		}()
	}
}

I get the follow error:

$ go run bin/faker.go 
fatal error: concurrent map read and map write

goroutine 19 [running]:
runtime.throw(0x1122ca3, 0x21)
	/usr/local/Cellar/go/1.14.1/libexec/src/runtime/panic.go:1114 +0x72 fp=0xc000221760 sp=0xc000221730 pc=0x1030a22
runtime.mapaccess1_faststr(0x10f41a0, 0xc00009a600, 0x10e3609, 0x5, 0x10eb480)
	/usr/local/Cellar/go/1.14.1/libexec/src/runtime/map_faststr.go:21 +0x43c fp=0xc0002217d0 sp=0xc000221760 pc=0x10120fc
github.com/bxcodec/faker.getValue(0x10fb380, 0xc00020e580, 0x199, 0x10fb301, 0x10fb380, 0xc00020e580, 0xc00020e500)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/faker.go:422 +0x1e2e fp=0xc000221b30 sp=0xc0002217d0 pc=0x10cbade
github.com/bxcodec/faker.getValue(0x10e58e0, 0xc00020e540, 0xc000221f48, 0x107ab78, 0x10fb380, 0xb7a0, 0x10e58e0)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/faker.go:356 +0x174a fp=0xc000221e90 sp=0xc000221b30 pc=0x10cb3fa
github.com/bxcodec/faker.FakeData(0x10e58e0, 0xc00020e540, 0x16, 0xc00020e501)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/faker.go:281 +0x1c6 fp=0xc000221f88 sp=0xc000221e90 pc=0x10c9896
main.main.func1(0x1145580, 0x10fb380)
	/Users/pioz/Code/go/src/github.com/pioz/ct/bin/faker.go:23 +0x81 fp=0xc000221fd0 sp=0xc000221f88 pc=0x10da051
runtime.goexit()
	/usr/local/Cellar/go/1.14.1/libexec/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000221fd8 sp=0xc000221fd0 pc=0x105d6a1
created by main.main
	/Users/pioz/Code/go/src/github.com/pioz/ct/bin/faker.go:20 +0xaf

goroutine 1 [runnable]:
runtime.gopark(0x0, 0x0, 0xc000001008, 0x1)
	/usr/local/Cellar/go/1.14.1/libexec/src/runtime/proc.go:287 +0x130
runtime.main()
	/usr/local/Cellar/go/1.14.1/libexec/src/runtime/proc.go:222 +0x28c
runtime.goexit()
	/usr/local/Cellar/go/1.14.1/libexec/src/runtime/asm_amd64.s:1373 +0x1

goroutine 20 [runnable]:
github.com/bxcodec/faker/support/slice.ContainsValue(0xc000226000, 0xaf, 0x100, 0x10eb480, 0xc00010d5b0, 0xc00010d5b0)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/support/slice/helpers.go:21 +0x82
github.com/bxcodec/faker.getValue(0x10fb380, 0xc000115240, 0x199, 0x10fb301, 0x10fb380, 0xc000115240, 0xc0001151c0)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/faker.go:422 +0x1e6b
github.com/bxcodec/faker.getValue(0x10e58e0, 0xc000115200, 0xc000195f48, 0x107ab78, 0x10fb380, 0xb7a0, 0x10e58e0)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/faker.go:356 +0x174a
github.com/bxcodec/faker.FakeData(0x10e58e0, 0xc000115200, 0x16, 0xc000115201)
	/Users/pioz/Code/go/src/github.com/bxcodec/faker/faker.go:281 +0x1c6
main.main.func1(0x1145580, 0x10fb380)
	/Users/pioz/Code/go/src/github.com/pioz/ct/bin/faker.go:23 +0x81
created by main.main
	/Users/pioz/Code/go/src/github.com/pioz/ct/bin/faker.go:20 +0xaf
...

If I remove the go keyword all works fine.
If I remove the unique option in the Email field tag all works fine.

@bxcodec
Copy link
Owner

bxcodec commented Jun 24, 2020

We haven't try to test this in a concurrent way.

My suggestion, I think you can add mutex on inside your goroutine.

mutex.Lock()
for j := 0; j < 1000; j++ {
    faker.FakeData(modelCopy)
}
mutex.Unlock()

How about it?

@pioz
Copy link
Contributor Author

pioz commented Jun 24, 2020

This is the playground: https://play.golang.org/p/1T1aAsWgmhu

It would be nice if faker managed concurrency internally.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants