Commit 98a5f52e authored by Russ Cox's avatar Russ Cox

os: avoid error result when dir is removed out from under RemoveAll

Fixes #7776.

LGTM=bradfitz
R=golang-codereviews, bradfitz
CC=golang-codereviews, r
https://golang.org/cl/145860043
parent 76c75481
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
"runtime" "runtime"
"sort" "sort"
"strings" "strings"
"sync"
"syscall" "syscall"
"testing" "testing"
"text/template" "text/template"
...@@ -1403,3 +1404,44 @@ func TestNilFileMethods(t *testing.T) { ...@@ -1403,3 +1404,44 @@ func TestNilFileMethods(t *testing.T) {
} }
} }
} }
func mkdirTree(t *testing.T, root string, level, max int) {
if level >= max {
return
}
level++
for i := 'a'; i < 'c'; i++ {
dir := filepath.Join(root, string(i))
if err := Mkdir(dir, 0700); err != nil {
t.Fatal(err)
}
mkdirTree(t, dir, level, max)
}
}
// Test that simultaneous RemoveAll do not report an error.
// As long as it gets removed, we should be happy.
func TestRemoveAllRace(t *testing.T) {
n := runtime.GOMAXPROCS(16)
defer runtime.GOMAXPROCS(n)
root, err := ioutil.TempDir("", "issue")
if err != nil {
t.Fatal(err)
}
mkdirTree(t, root, 1, 6)
hold := make(chan struct{})
var wg sync.WaitGroup
for i := 0; i < 4; i++ {
wg.Add(1)
go func() {
defer wg.Done()
<-hold
err := RemoveAll(root)
if err != nil {
t.Errorf("unexpected error: %T, %q", err, err)
}
}()
}
close(hold) // let workers race to remove root
wg.Wait()
}
...@@ -66,7 +66,7 @@ func MkdirAll(path string, perm FileMode) error { ...@@ -66,7 +66,7 @@ func MkdirAll(path string, perm FileMode) error {
func RemoveAll(path string) error { func RemoveAll(path string) error {
// Simple case: if Remove works, we're done. // Simple case: if Remove works, we're done.
err := Remove(path) err := Remove(path)
if err == nil { if err == nil || IsNotExist(err) {
return nil return nil
} }
...@@ -116,6 +116,9 @@ func RemoveAll(path string) error { ...@@ -116,6 +116,9 @@ func RemoveAll(path string) error {
// Remove directory. // Remove directory.
err1 := Remove(path) err1 := Remove(path)
if err1 == nil || IsNotExist(err1) {
return nil
}
if err == nil { if err == nil {
err = err1 err = err1
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment