Fix data races in MemMapFs

Concurrent modifications of the file system while calling
ReadDir was causing data races and sometimes panics.
This commit is contained in:
jszwec 2017-07-22 18:23:01 -04:00 committed by Bjørn Erik Pedersen
parent 9be650865e
commit 36f8810e2e
2 changed files with 46 additions and 0 deletions

View File

@ -66,7 +66,10 @@ func (m *MemMapFs) unRegisterWithParent(fileName string) error {
if parent == nil {
log.Panic("parent of ", f.Name(), " is nil")
}
parent.Lock()
mem.RemoveFromMemDir(parent, f)
parent.Unlock()
return nil
}
@ -99,8 +102,10 @@ func (m *MemMapFs) registerWithParent(f *mem.FileData) {
}
}
parent.Lock()
mem.InitializeDir(parent)
mem.AddToMemDir(parent, f)
parent.Unlock()
}
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {

View File

@ -1,6 +1,7 @@
package afero
import (
"fmt"
"os"
"path/filepath"
"runtime"
@ -343,3 +344,43 @@ func TestRacingDeleteAndClose(t *testing.T) {
}()
close(in)
}
// This test should be run with the race detector on:
// go test -run TestMemFsDataRace -race
func TestMemFsDataRace(t *testing.T) {
const dir = "test_dir"
fs := NewMemMapFs()
if err := fs.MkdirAll(dir, 0777); err != nil {
t.Fatal(err)
}
const n = 1000
done := make(chan struct{})
go func() {
defer close(done)
for i := 0; i < n; i++ {
fname := filepath.Join(dir, fmt.Sprintf("%d.txt", i))
if err := WriteFile(fs, fname, []byte(""), 0777); err != nil {
panic(err)
}
if err := fs.Remove(fname); err != nil {
panic(err)
}
}
}()
loop:
for {
select {
case <-done:
break loop
default:
_, err := ReadDir(fs, dir)
if err != nil {
t.Fatal(err)
}
}
}
}