Skip to content

Commit 820ad17

Browse files
cmd/go: remove work directory on usage error
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>
1 parent 7c388cc commit 820ad17

File tree

10 files changed

+71
-19
lines changed

10 files changed

+71
-19
lines changed

src/cmd/go/go_test.go

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,18 @@ func TestMain(m *testing.M) {
146146
select {}
147147
}
148148

149-
dir, err := ioutil.TempDir(os.Getenv("GOTMPDIR"), "cmd-go-test-")
149+
// Run with a temporary TMPDIR to check that the tests don't
150+
// leave anything behind.
151+
topTmpdir, err := ioutil.TempDir("", "cmd-go-test-")
152+
if err != nil {
153+
log.Fatal(err)
154+
}
155+
if !*testWork {
156+
defer removeAll(topTmpdir)
157+
}
158+
os.Setenv(tempEnvName(), topTmpdir)
159+
160+
dir, err := ioutil.TempDir(topTmpdir, "tmpdir")
150161
if err != nil {
151162
log.Fatal(err)
152163
}
@@ -258,6 +269,23 @@ func TestMain(m *testing.M) {
258269
removeAll(testTmpDir) // os.Exit won't run defer
259270
}
260271

272+
if !*testWork {
273+
// There shouldn't be anything left in topTmpdir.
274+
dirf, err := os.Open(topTmpdir)
275+
if err != nil {
276+
log.Fatal(err)
277+
}
278+
names, err := dirf.Readdirnames(0)
279+
if err != nil {
280+
log.Fatal(err)
281+
}
282+
if len(names) > 0 {
283+
log.Fatalf("unexpected files left in tmpdir: %v", names)
284+
}
285+
286+
removeAll(topTmpdir)
287+
}
288+
261289
os.Exit(r)
262290
}
263291

@@ -5059,7 +5087,8 @@ func TestExecBuildX(t *testing.T) {
50595087
obj := tg.path("main")
50605088
tg.run("build", "-x", "-o", obj, src)
50615089
sh := tg.path("test.sh")
5062-
err := ioutil.WriteFile(sh, []byte("set -e\n"+tg.getStderr()), 0666)
5090+
cmds := tg.getStderr()
5091+
err := ioutil.WriteFile(sh, []byte("set -e\n"+cmds), 0666)
50635092
if err != nil {
50645093
t.Fatal(err)
50655094
}
@@ -5090,6 +5119,12 @@ func TestExecBuildX(t *testing.T) {
50905119
if string(out) != "hello" {
50915120
t.Fatalf("got %q; want %q", out, "hello")
50925121
}
5122+
5123+
matches := regexp.MustCompile(`^WORK=(.*)\n`).FindStringSubmatch(cmds)
5124+
if len(matches) == 0 {
5125+
t.Fatal("no WORK directory")
5126+
}
5127+
tg.must(os.RemoveAll(matches[1]))
50935128
}
50945129

50955130
func TestParallelNumber(t *testing.T) {

src/cmd/go/internal/base/base.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ func (c *Command) Name() string {
8282
func (c *Command) Usage() {
8383
fmt.Fprintf(os.Stderr, "usage: %s\n", c.UsageLine)
8484
fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", c.LongName())
85-
os.Exit(2)
85+
SetExitStatus(2)
86+
Exit()
8687
}
8788

8889
// Runnable reports whether the command can be run; otherwise

src/cmd/go/internal/cmdflag/flag.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ func SyntaxError(cmd, msg string) {
6666
} else {
6767
fmt.Fprintf(os.Stderr, `run "go help %s" for more information`+"\n", cmd)
6868
}
69-
os.Exit(2)
69+
base.SetExitStatus(2)
70+
base.Exit()
7071
}
7172

7273
// AddKnownFlags registers the flags in defns with base.AddKnownFlag.

src/cmd/go/internal/help/help.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ Args:
6363
helpSuccess = " " + strings.Join(args[:i], " ")
6464
}
6565
fmt.Fprintf(os.Stderr, "go help %s: unknown help topic. Run '%s'.\n", strings.Join(args, " "), helpSuccess)
66-
os.Exit(2) // failed at 'go help cmd'
66+
base.SetExitStatus(2) // failed at 'go help cmd'
67+
base.Exit()
6768
}
6869

6970
if len(cmd.Commands) > 0 {
@@ -167,7 +168,8 @@ func tmpl(w io.Writer, text string, data interface{}) {
167168
if ew.err != nil {
168169
// I/O error writing. Ignore write on closed pipe.
169170
if strings.Contains(ew.err.Error(), "pipe") {
170-
os.Exit(1)
171+
base.SetExitStatus(1)
172+
base.Exit()
171173
}
172174
base.Fatalf("writing output: %v", ew.err)
173175
}

src/cmd/go/internal/vet/vetflag.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
7676
vetcmd.Stdout = out
7777
if err := vetcmd.Run(); err != nil {
7878
fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err)
79-
os.Exit(2)
79+
base.SetExitStatus(2)
80+
base.Exit()
8081
}
8182
var analysisFlags []struct {
8283
Name string
@@ -85,7 +86,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
8586
}
8687
if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil {
8788
fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err)
88-
os.Exit(2)
89+
base.SetExitStatus(2)
90+
base.Exit()
8991
}
9092

9193
// Add vet's flags to vetflagDefn.
@@ -134,7 +136,8 @@ func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
134136
if f == nil {
135137
fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
136138
fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
137-
os.Exit(2)
139+
base.SetExitStatus(2)
140+
base.Exit()
138141
}
139142
if f.Value != nil {
140143
if err := f.Value.Set(value); err != nil {
@@ -182,5 +185,6 @@ func usage() {
182185
}
183186
fmt.Fprintf(os.Stderr, "Run '%s -help' for the vet tool's flags.\n", cmd)
184187

185-
os.Exit(2)
188+
base.SetExitStatus(2)
189+
base.Exit()
186190
}

src/cmd/go/internal/work/action.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,12 +248,14 @@ func (b *Builder) Init() {
248248

249249
if _, ok := cfg.OSArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" {
250250
fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch)
251-
os.Exit(2)
251+
base.SetExitStatus(2)
252+
base.Exit()
252253
}
253254
for _, tag := range cfg.BuildContext.BuildTags {
254255
if strings.Contains(tag, ",") {
255256
fmt.Fprintf(os.Stderr, "cmd/go: -tags space-separated list contains comma\n")
256-
os.Exit(2)
257+
base.SetExitStatus(2)
258+
base.Exit()
257259
}
258260
}
259261
}

src/cmd/go/internal/work/exec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2327,7 +2327,7 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
23272327
// version of GCC, so some systems have frozen on it.
23282328
// Now we pass an empty file on stdin, which should work at least for
23292329
// GCC and clang.
2330-
cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-")
2330+
cmdArgs := str.StringList(compiler, flag, "-c", "-x", "c", "-", "-o", os.DevNull)
23312331
if cfg.BuildN || cfg.BuildX {
23322332
b.Showcmd(b.WorkDir, "%s || true", joinUnambiguously(cmdArgs))
23332333
if cfg.BuildN {

src/cmd/go/internal/work/gccgo.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ func checkGccgoBin() {
5656
return
5757
}
5858
fmt.Fprintf(os.Stderr, "cmd/go: gccgo: %s\n", gccgoErr)
59-
os.Exit(2)
59+
base.SetExitStatus(2)
60+
base.Exit()
6061
}
6162

6263
func (tools gccgoToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, symabis string, asmhdr bool, gofiles []string) (ofile string, output []byte, err error) {

src/cmd/go/internal/work/init.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ func BuildInit() {
2929
p, err := filepath.Abs(cfg.BuildPkgdir)
3030
if err != nil {
3131
fmt.Fprintf(os.Stderr, "go %s: evaluating -pkgdir: %v\n", flag.Args()[0], err)
32-
os.Exit(2)
32+
base.SetExitStatus(2)
33+
base.Exit()
3334
}
3435
cfg.BuildPkgdir = p
3536
}
@@ -41,16 +42,19 @@ func instrumentInit() {
4142
}
4243
if cfg.BuildRace && cfg.BuildMSan {
4344
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
44-
os.Exit(2)
45+
base.SetExitStatus(2)
46+
base.Exit()
4547
}
4648
if cfg.BuildMSan && !sys.MSanSupported(cfg.Goos, cfg.Goarch) {
4749
fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
48-
os.Exit(2)
50+
base.SetExitStatus(2)
51+
base.Exit()
4952
}
5053
if cfg.BuildRace {
5154
if !sys.RaceDetectorSupported(cfg.Goos, cfg.Goarch) {
5255
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])
53-
os.Exit(2)
56+
base.SetExitStatus(2)
57+
base.Exit()
5458
}
5559
}
5660
mode := "race"
@@ -61,7 +65,8 @@ func instrumentInit() {
6165

6266
if !cfg.BuildContext.CgoEnabled {
6367
fmt.Fprintf(os.Stderr, "go %s: %s requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0], modeFlag)
64-
os.Exit(2)
68+
base.SetExitStatus(2)
69+
base.Exit()
6570
}
6671
forcedGcflags = append(forcedGcflags, modeFlag)
6772
forcedLdflags = append(forcedLdflags, modeFlag)

src/cmd/go/script_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ func (ts *testScript) cmdCc(neg bool, args []string) {
399399
var b work.Builder
400400
b.Init()
401401
ts.cmdExec(neg, append(b.GccCmd(".", ""), args...))
402+
os.RemoveAll(b.WorkDir)
402403
}
403404

404405
// cd changes to a different directory.

0 commit comments

Comments
 (0)