mirror of https://github.com/spf13/afero.git
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:
parent
9be650865e
commit
36f8810e2e
|
@ -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 {
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue