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

View File

@ -1,6 +1,7 @@
package afero package afero
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -343,3 +344,43 @@ func TestRacingDeleteAndClose(t *testing.T) {
}() }()
close(in) 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)
}
}
}
}