summaryrefslogtreecommitdiff
path: root/src/os
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-09-18 14:48:47 -0400
committerRuss Cox <rsc@golang.org>2014-09-18 14:48:47 -0400
commit433566655a72738d3f2f700c4134226a88e6293d (patch)
tree0d1a03dd0ef67c23c76a33b275885bff0ada7f37 /src/os
parent798fe2075f9195866b3a8ea54e259f82bde116bf (diff)
downloadgo-433566655a72738d3f2f700c4134226a88e6293d.tar.gz
os: avoid error result when dir is removed out from under RemoveAll
Fixes issue 7776. LGTM=bradfitz R=golang-codereviews, bradfitz CC=golang-codereviews, r https://codereview.appspot.com/145860043
Diffstat (limited to 'src/os')
-rw-r--r--src/os/os_test.go42
-rw-r--r--src/os/path.go5
2 files changed, 46 insertions, 1 deletions
diff --git a/src/os/os_test.go b/src/os/os_test.go
index 0224c9b01..7a2849741 100644
--- a/src/os/os_test.go
+++ b/src/os/os_test.go
@@ -18,6 +18,7 @@ import (
"runtime"
"sort"
"strings"
+ "sync"
"syscall"
"testing"
"text/template"
@@ -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()
+}
diff --git a/src/os/path.go b/src/os/path.go
index 02a77ec80..6cc69403b 100644
--- a/src/os/path.go
+++ b/src/os/path.go
@@ -66,7 +66,7 @@ func MkdirAll(path string, perm FileMode) error {
func RemoveAll(path string) error {
// Simple case: if Remove works, we're done.
err := Remove(path)
- if err == nil {
+ if err == nil || IsNotExist(err) {
return nil
}
@@ -116,6 +116,9 @@ func RemoveAll(path string) error {
// Remove directory.
err1 := Remove(path)
+ if err1 == nil || IsNotExist(err1) {
+ return nil
+ }
if err == nil {
err = err1
}