Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fatal error: concurrent map writes #4

Closed
qiukeren opened this issue Mar 9, 2021 · 2 comments
Closed

fatal error: concurrent map writes #4

qiukeren opened this issue Mar 9, 2021 · 2 comments

Comments

@qiukeren
Copy link

qiukeren commented Mar 9, 2021


fatal error: concurrent map writes

goroutine 53 [running]:
runtime.throw(0x21d9a37, 0x15)
        /usr/local/go/src/runtime/panic.go:1117 +0x72 fp=0xc00059a5a8 sp=0xc00059a578 pc=0x56b952
runtime.mapdelete(0x204f0a0, 0xc00032e180, 0xc00059a638)
        /usr/local/go/src/runtime/map.go:702 +0x46e fp=0xc00059a608 sp=0xc00059a5a8 pc=0x544c6e
github.com/zekroTJA/timedmap.(*TimedMap).expireElement(0xc000618040, 0x2000940, 0xc007e1d690, 0x0, 0xc006694300)
        /root/go/pkg/mod/github.com/zekro!t!j!a/timedmap@v1.3.0/timedmap.go:177 +0xc5 fp=0xc00059a660 sp=0xc00059a608 pc=0x10756e5
github.com/zekroTJA/timedmap.(*TimedMap).cleanUp(0xc000618040)
        /root/go/pkg/mod/github.com/zekro!t!j!a/timedmap@v1.3.0/timedmap.go:190 +0x1a9 fp=0xc00059a758 sp=0xc00059a660 pc=0x10758a9
github.com/zekroTJA/timedmap.New.func1(0xc0000cc3c0, 0xc000618040)
        /root/go/pkg/mod/github.com/zekro!t!j!a/timedmap@v1.3.0/timedmap.go:62 +0x97 fp=0xc00059a7d0 sp=0xc00059a758 pc=0x1075f77
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1371 +0x1 fp=0xc00059a7d8 sp=0xc00059a7d0 pc=0x5a1ce1
created by github.com/zekroTJA/timedmap.New
        /root/go/pkg/mod/github.com/zekro!t!j!a/timedmap@v1.3.0/timedmap.go:58 +0xc5

@qiukeren
Copy link
Author

qiukeren commented Mar 9, 2021

离谱的是 我自己跑bench跑不出来这个结果

it is confusing i can't provide it with main.


package main

import (
	"github.com/remeh/sizedwaitgroup"
	"github.com/zekroTJA/timedmap"
	"math/rand"
	"time"
)

func main() {
	tm := timedmap.New(5 * time.Millisecond)
	rand.Seed(time.Now().UnixNano())

	swg := sizedwaitgroup.New(80)
	for i := 0; i < 5000000000; i++ {
		swg.Add()
		go func(i int) {
			defer swg.Done()
			//k := RandStringRunes(10)
			k := "a"
			tm.Set(k, rand.Int31(), 3*time.Millisecond)
		}(i)
	}
	swg.Wait()
}

@qiukeren qiukeren closed this as completed Mar 9, 2021
zekroTJA added a commit that referenced this issue Mar 9, 2021
@zekroTJA
Copy link
Owner

zekroTJA commented Mar 9, 2021

Well, that's actually an issue when writing to the map while concurrently reading an existing but expired value, which then would be removed from the map on getting it. The call to expireElement() is not protected by a RWLock, so the concurrent map write panic occurs.

I was actually able to reproduce the behavior in the following test:

timedmap/timedmap_test.go

Lines 279 to 298 in d533e81

func TestGetExpiredConcurrent(t *testing.T) {
tm := New(dCleanupTick)
wg := sync.WaitGroup{}
for i := 0; i < 50000; i++ {
wg.Add(1)
go func() {
defer wg.Done()
tm.Set(1, 1, 0)
}()
wg.Add(1)
go func() {
defer wg.Done()
tm.GetValue(1)
}()
}
wg.Wait()
}

Result:
https://github.com/zekroTJA/timedmap/runs/2065005503?check_suite_focus=true#step:5:53

Now, it should be fixed with this change: e8e3b1e.

Thank you for the issue. ^^

@zekroTJA zekroTJA reopened this Mar 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants