]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: remove work directory on usage error
authorIan Lance Taylor <iant@golang.org>
Wed, 20 Feb 2019 23:15:18 +0000 (15:15 -0800)
committerIan Lance Taylor <iant@golang.org>
Fri, 1 Mar 2019 18:26:37 +0000 (18:26 +0000)
Ensure that cmd/go consistently calls base.Exit rather than os.Exit,
so that we don't incorrectly leave the work directory around on exit.

Test this by modifying the testsuite to run all the tests with TMPDIR
set to a temporary directory, and then check that no files are left
behind in that temporary directory. Adjust a couple of tests to make
this approach work.

Updates #30500
Updates https://gcc.gnu.org/PR89406

Change-Id: Ib6a5fc8a288a6cf4713022baa2b8dfefad62ba34
Reviewed-on: https://go-review.googlesource.com/c/163237
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
src/cmd/go/go_test.go
src/cmd/go/internal/base/base.go
src/cmd/go/internal/cmdflag/flag.go
src/cmd/go/internal/help/help.go
src/cmd/go/internal/vet/vetflag.go
src/cmd/go/internal/work/action.go
src/cmd/go/internal/work/exec.go
src/cmd/go/internal/work/gccgo.go
src/cmd/go/internal/work/init.go
src/cmd/go/script_test.go

index 866241bf39dcf27bcedbe1db7fbe2f44569fef2b..dfada6c806a6c7edf44a0a068d6850c05083f4ab 100644 (file)
@@ -146,7 +146,18 @@ func TestMain(m *testing.M) {
                select {}
        }
 
-       dir, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "cmd-go-test-")
+       // Run with a temporary TMPDIR to check that the tests don't
+       // leave anything behind.
+       topTmpdir, err := ioutil.TempDir("", "cmd-go-test-")
+       if err != nil {
+               log.Fatal(err)
+       }
+       if !*testWork {
+               defer removeAll(topTmpdir)
+       }
+       os.Setenv(tempEnvName(), topTmpdir)
+
+       dir, err := ioutil.TempDir(topTmpdir, "tmpdir")
        if err != nil {
                log.Fatal(err)
        }
@@ -258,6 +269,23 @@ func TestMain(m *testing.M) {
                removeAll(testTmpDir) // os.Exit won't run defer
        }
 
+       if !*testWork {
+               // There shouldn't be anything left in topTmpdir.
+               dirf, err := os.Open(topTmpdir)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               names, err := dirf.Readdirnames(0)
+               if err != nil {
+                       log.Fatal(err)
+               }
+               if len(names) > 0 {
+                       log.Fatalf("unexpected files left in tmpdir: %v", names)
+               }
+
+               removeAll(topTmpdir)
+       }
+
        os.Exit(r)
 }
 
@@ -5059,7 +5087,8 @@ func TestExecBuildX(t *testing.T) {
        obj := tg.path("main")
        tg.run("build", "-x", "-o", obj, src)
        sh := tg.path("test.sh")
-       err := ioutil.WriteFile(sh, []byte("set -e\n"+tg.getStderr()), 0666)
+       cmds := tg.getStderr()
+       err := ioutil.WriteFile(sh, []byte("set -e\n"+cmds), 0666)
        if err != nil {
                t.Fatal(err)
        }
@@ -5090,6 +5119,12 @@ func TestExecBuildX(t *testing.T) {
        if string(out) != "hello" {
                t.Fatalf("got %q; want %q", out, "hello")
        }
+
+       matches := regexp.MustCompile(`^WORK=(.*)\n`).FindStringSubmatch(cmds)
+       if len(matches) == 0 {
+               t.Fatal("no WORK directory")
+       }
+       tg.must(os.RemoveAll(matches[1]))
 }
 
 func TestParallelNumber(t *testing.T) {
index e7f54c9a365fef809ba8f32e5e6ebaece13838e6..bf810ff7622ac7ba7bcfaf1f9ed9bdaddcb48606 100644 (file)
@@ -82,7 +82,8 @@ func (c *Command) Name() string {
 func (c *Command) Usage() {
        fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine)
        fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName())
-       os.Exit(2)
+       SetExitStatus(2)
+       Exit()
 }
 
 // Runnable reports whether the command can be run; otherwise
index 7f2c53def8fa2b3ce5baa9e54251d508bf5a926e..3f934328fe10f784101547f50eda5affb2e39bc2 100644 (file)
@@ -66,7 +66,8 @@ func SyntaxError(cmd, msg string) {
        } else {
                fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd)
        }
-       os.Exit(2)
+       base.SetExitStatus(2)
+       base.Exit()
 }
 
 // AddKnownFlags registers the flags in defns with base.AddKnownFlag.
index 312a29590f43f0fbd65aea08de3caff15cdce6bc..121deb70a58904a72226b4c4bafdd225d5fba266 100644 (file)
@@ -63,7 +63,8 @@ Args:
                        helpSuccess = " " + strings.Join(args[:i], " ")
                }
                fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
-               os.Exit(2) // failed at 'go help cmd'
+               base.SetExitStatus(2) // failed at 'go help cmd'
+               base.Exit()
        }
 
        if len(cmd.Commands) > 0 {
@@ -167,7 +168,8 @@ func tmpl(w io.Writer, text string, data interface{}) {
        if ew.err != nil {
                // I/O error writing. Ignore write on closed pipe.
                if strings.Contains(ew.err.Error(), "pipe") {
-                       os.Exit(1)
+                       base.SetExitStatus(1)
+                       base.Exit()
                }
                base.Fatalf("writing output: %v", ew.err)
        }
index 37342f41633420dd90d530f006021b24519ed029..cbe7f8ce08c02d962d8f0228ec4fcded5337daf5 100644 (file)
@@ -76,7 +76,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
        vetcmd.Stdout = out
        if err := vetcmd.Run(); err != nil {
                fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err)
-               os.Exit(2)
+               base.SetExitStatus(2)
+               base.Exit()
        }
        var analysisFlags []struct {
                Name  string
@@ -85,7 +86,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
        }
        if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil {
                fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err)
-               os.Exit(2)
+               base.SetExitStatus(2)
+               base.Exit()
        }
 
        // Add vet's flags to vetflagDefn.
@@ -134,7 +136,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
                if f == nil {
                        fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
                        fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
-                       os.Exit(2)
+                       base.SetExitStatus(2)
+                       base.Exit()
                }
                if f.Value != nil {
                        if err := f.Value.Set(value); err != nil {
@@ -182,5 +185,6 @@ func usage() {
        }
        fmt.Fprintf(os.Stderr, "Run '%s -help' for the vet tool's flags.\n", cmd)
 
-       os.Exit(2)
+       base.SetExitStatus(2)
+       base.Exit()
 }
index 1f91046eb11045dbb294955d0382822a9efad318..a47b9ba370217b857d2ea886c1f8339e4b63c9aa 100644 (file)
@@ -248,12 +248,14 @@ func (b *Builder) Init() {
 
        if _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" {
                fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch)
-               os.Exit(2)
+               base.SetExitStatus(2)
+               base.Exit()
        }
        for _, tag := range cfg.BuildContext.BuildTags {
                if strings.Contains(tag, ",") {
                        fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n")
-                       os.Exit(2)
+                       base.SetExitStatus(2)
+                       base.Exit()
                }
        }
 }
index 37766c2ce5746303642ff86a465f7c6ffec39564..bb71faac9cf2a5ac8b560427af8c0809aada68cc 100644 (file)
@@ -2327,7 +2327,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
        // version of GCC, so some systems have frozen on it.
        // Now we pass an empty file on stdin, which should work at least for
        // GCC and clang.
-       cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-")
+       cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", os.DevNull)
        if cfg.BuildN || cfg.BuildX {
                b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
                if cfg.BuildN {
index 184d2919ca61a8643d5552d4187326f9fb0662e9..053d32dc0b8cb4cb03b6d848431ce2af545cacd5 100644 (file)
@@ -56,7 +56,8 @@ func checkGccgoBin() {
                return
        }
        fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr)
-       os.Exit(2)
+       base.SetExitStatus(2)
+       base.Exit()
 }
 
 func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {
index 693a53e9ab78d012f493bb619f5471f6c2d1f9ed..3381ab544c7f4aad84c55db6c83bdcacf06f0da3 100644 (file)
@@ -29,7 +29,8 @@ func BuildInit() {
                p, err := filepath.Abs(cfg.BuildPkgdir)
                if err != nil {
                        fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err)
-                       os.Exit(2)
+                       base.SetExitStatus(2)
+                       base.Exit()
                }
                cfg.BuildPkgdir = p
        }
@@ -41,16 +42,19 @@ func instrumentInit() {
        }
        if cfg.BuildRace && cfg.BuildMSan {
                fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
-               os.Exit(2)
+               base.SetExitStatus(2)
+               base.Exit()
        }
        if cfg.BuildMSan && !sys.MSanSupported(cfg.Goos, cfg.Goarch) {
                fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
-               os.Exit(2)
+               base.SetExitStatus(2)
+               base.Exit()
        }
        if cfg.BuildRace {
                if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) {
                        fmt.Fprintf(os.Stderr, "go %s: -race is only supported on linux/amd64, linux/ppc64le, linux/arm64, freebsd/amd64, netbsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
-                       os.Exit(2)
+                       base.SetExitStatus(2)
+                       base.Exit()
                }
        }
        mode := "race"
@@ -61,7 +65,8 @@ func instrumentInit() {
 
        if !cfg.BuildContext.CgoEnabled {
                fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
-               os.Exit(2)
+               base.SetExitStatus(2)
+               base.Exit()
        }
        forcedGcflags = append(forcedGcflags, modeFlag)
        forcedLdflags = append(forcedLdflags, modeFlag)
index c5e0064036784d97d4d3f7817a95e24649b8c796..e204471beb8d61fff05e387c4a49ce1aec47b410 100644 (file)
@@ -399,6 +399,7 @@ func (ts *testScript) cmdCc(neg bool, args []string) {
        var b work.Builder
        b.Init()
        ts.cmdExec(neg, append(b.GccCmd(".", ""), args...))
+       os.RemoveAll(b.WorkDir)
 }
 
 // cd changes to a different directory.