From fe8b6453a7fa250db561c7b1305cf906e1e1efca Mon Sep 17 00:00:00 2001 From: Dan Willemsen Date: Sat, 12 May 2018 18:34:24 -0700 Subject: [PATCH] Handle readonly directories in tmpdir Some tests make their temporary directories readonly. If they fail or crash before cleaning up, they could leave these readonly directories behind with files in them. os.RemoveAll fails with an error in this case, and we can't start the build until they're removed. Test: `m blueprint_tools` to run the new go tests Change-Id: I761f96579e96167ebfd98c6cca59765bd50536ec --- ui/build/util.go | 21 ++++++++++++++++++--- ui/build/util_test.go | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/ui/build/util.go b/ui/build/util.go index f698ccd0b..96088fe78 100644 --- a/ui/build/util.go +++ b/ui/build/util.go @@ -62,9 +62,24 @@ func ensureDirectoriesExist(ctx Context, dirs ...string) { func ensureEmptyDirectoriesExist(ctx Context, dirs ...string) { // remove all the directories for _, dir := range dirs { - err := os.RemoveAll(dir) - if err != nil { - ctx.Fatalf("Error removing %s: %q\n", dir, err) + seenErr := map[string]bool{} + for { + err := os.RemoveAll(dir) + if err == nil { + break + } + + if pathErr, ok := err.(*os.PathError); !ok || + dir == pathErr.Path || seenErr[pathErr.Path] { + + ctx.Fatalf("Error removing %s: %q\n", dir, err) + } else { + seenErr[pathErr.Path] = true + err = os.Chmod(filepath.Dir(pathErr.Path), 0700) + if err != nil { + ctx.Fatal(err) + } + } } } // recreate all the directories diff --git a/ui/build/util_test.go b/ui/build/util_test.go index e85eadad2..0e0dbdfb0 100644 --- a/ui/build/util_test.go +++ b/ui/build/util_test.go @@ -14,7 +14,41 @@ package build -import "testing" +import ( + "io/ioutil" + "os" + "path/filepath" + "testing" + + "android/soong/ui/logger" +) + +func TestEnsureEmptyDirs(t *testing.T) { + ctx := testContext() + defer logger.Recover(func(err error) { + t.Error(err) + }) + + tmpDir, err := ioutil.TempDir("", "") + if err != nil { + t.Fatal(err) + } + defer func() { + err := os.RemoveAll(tmpDir) + if err != nil { + t.Errorf("Error removing tmpDir: %v", err) + } + }() + + ensureEmptyDirectoriesExist(ctx, filepath.Join(tmpDir, "a/b")) + + err = os.Chmod(filepath.Join(tmpDir, "a"), 0555) + if err != nil { + t.Fatalf("Failed to chown: %v", err) + } + + ensureEmptyDirectoriesExist(ctx, filepath.Join(tmpDir, "a")) +} func TestStripAnsiEscapes(t *testing.T) { testcases := []struct {