Skip to content

testing: add panic on any os.Exit call, not only zero code #61864

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/cmd/go/internal/test/internal/genflags/testflag.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func ShortTestFlags() []string {
}

switch name {
case "testlogfile", "paniconexit0", "fuzzcachedir", "fuzzworker", "gocoverdir":
case "testlogfile", "paniconexit0", "paniconexit", "fuzzcachedir", "fuzzworker", "gocoverdir":
// These flags are only for use by cmd/go.
default:
names = append(names, name)
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/go/internal/test/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1315,7 +1315,7 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
if !r.c.disableCache && len(execCmd) == 0 {
testlogArg = []string{"-test.testlogfile=" + a.Objdir + "testlog.txt"}
}
panicArg := "-test.paniconexit0"
panicArg := "-test.paniconexit"
fuzzArg := []string{}
if testFuzz != "" {
fuzzCacheDir := filepath.Join(cache.Default().FuzzDir(), a.Package.ImportPath)
Expand Down
24 changes: 12 additions & 12 deletions src/internal/testlog/exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ package testlog

import "sync"

// PanicOnExit0 reports whether to panic on a call to os.Exit(0).
// PanicOnExit reports whether to panic on a call to os.Exit.
// This is in the testlog package because, like other definitions in
// package testlog, it is a hook between the testing package and the
// os package. This is used to ensure that an early call to os.Exit(0)
// does not cause a test to pass.
func PanicOnExit0() bool {
panicOnExit0.mu.Lock()
defer panicOnExit0.mu.Unlock()
return panicOnExit0.val
func PanicOnExit() bool {
panicOnExit.mu.Lock()
defer panicOnExit.mu.Unlock()
return panicOnExit.val
}

// panicOnExit0 is the flag used for PanicOnExit0. This uses a lock
// panicOnExit is the flag used for PanicOnExit. This uses a lock
// because the value can be cleared via a timer call that may race
// with calls to os.Exit
var panicOnExit0 struct {
var panicOnExit struct {
mu sync.Mutex
val bool
}

// SetPanicOnExit0 sets panicOnExit0 to v.
func SetPanicOnExit0(v bool) {
panicOnExit0.mu.Lock()
defer panicOnExit0.mu.Unlock()
panicOnExit0.val = v
// SetPanicOnExit sets panicOnExit to v.
func SetPanicOnExit(v bool) {
panicOnExit.mu.Lock()
defer panicOnExit.mu.Unlock()
panicOnExit.val = v
}
9 changes: 5 additions & 4 deletions src/os/proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package os

import (
"internal/itoa"
"internal/testlog"
"runtime"
"syscall"
Expand Down Expand Up @@ -60,11 +61,11 @@ func Getgroups() ([]int, error) {
//
// For portability, the status code should be in the range [0, 125].
func Exit(code int) {
if code == 0 && testlog.PanicOnExit0() {
// We were told to panic on calls to os.Exit(0).
if testlog.PanicOnExit() {
// We were told to panic on calls to os.Exit.
// This is used to fail tests that make an early
// unexpected call to os.Exit(0).
panic("unexpected call to os.Exit(0) during test")
// unexpected call to os.Exit.
panic("unexpected call to os.Exit(" + itoa.Itoa(code) + ") during test")
}

// Inform the runtime that os.Exit is being called. If -race is
Expand Down
6 changes: 3 additions & 3 deletions src/testing/internal/testdeps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ func (TestDeps) StopTestLog() error {
return err
}

// SetPanicOnExit0 tells the os package whether to panic on os.Exit(0).
func (TestDeps) SetPanicOnExit0(v bool) {
testlog.SetPanicOnExit0(v)
// SetPanicOnExit tells the os package whether to panic on os.Exit.
func (TestDeps) SetPanicOnExit(v bool) {
testlog.SetPanicOnExit(v)
}

func (TestDeps) CoordinateFuzzing(
Expand Down
18 changes: 10 additions & 8 deletions src/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,8 @@ func Init() {
blockProfileRate = flag.Int("test.blockprofilerate", 1, "set blocking profile `rate` (see runtime.SetBlockProfileRate)")
mutexProfile = flag.String("test.mutexprofile", "", "write a mutex contention profile to the named file after execution")
mutexProfileFraction = flag.Int("test.mutexprofilefraction", 1, "if >= 0, calls runtime.SetMutexProfileFraction()")
panicOnExit0 = flag.Bool("test.paniconexit0", false, "panic on call to os.Exit(0)")
panicOnExit0 = flag.Bool("test.paniconexit0", false, "deprecated, use `test.paniconexit` instead")
panicOnExit = flag.Bool("test.paniconexit", false, "panic on call to os.Exit")
traceFile = flag.String("test.trace", "", "write an execution trace to `file`")
timeout = flag.Duration("test.timeout", 0, "panic test binary after duration `d` (default 0, timeout disabled)")
cpuListStr = flag.String("test.cpu", "", "comma-separated `list` of cpu counts to run each test with")
Expand Down Expand Up @@ -467,6 +468,7 @@ var (
mutexProfile *string
mutexProfileFraction *int
panicOnExit0 *bool
panicOnExit *bool
traceFile *string
timeout *time.Duration
cpuListStr *string
Expand Down Expand Up @@ -1740,7 +1742,7 @@ func (f matchStringOnly) WriteProfileTo(string, io.Writer, int) error { return e
func (f matchStringOnly) ImportPath() string { return "" }
func (f matchStringOnly) StartTestLog(io.Writer) {}
func (f matchStringOnly) StopTestLog() error { return errMain }
func (f matchStringOnly) SetPanicOnExit0(bool) {}
func (f matchStringOnly) SetPanicOnExit(bool) {}
func (f matchStringOnly) CoordinateFuzzing(time.Duration, int64, time.Duration, int64, int, []corpusEntry, []reflect.Type, string, string) error {
return errMain
}
Expand Down Expand Up @@ -1787,7 +1789,7 @@ type M struct {
type testDeps interface {
ImportPath() string
MatchString(pat, str string) (bool, error)
SetPanicOnExit0(bool)
SetPanicOnExit(bool)
StartCPUProfile(io.Writer) error
StopCPUProfile()
StartTestLog(io.Writer)
Expand Down Expand Up @@ -2131,8 +2133,8 @@ func (m *M) before() {
m.deps.StartTestLog(f)
testlogFile = f
}
if *panicOnExit0 {
m.deps.SetPanicOnExit0(true)
if *panicOnExit || *panicOnExit0 {
m.deps.SetPanicOnExit(true)
}
}

Expand All @@ -2142,11 +2144,11 @@ func (m *M) after() {
m.writeProfiles()
})

// Restore PanicOnExit0 after every run, because we set it to true before
// Restore PanicOnExit after every run, because we set it to true before
// every run. Otherwise, if m.Run is called multiple times the behavior of
// os.Exit(0) will not be restored after the second run.
if *panicOnExit0 {
m.deps.SetPanicOnExit0(false)
if *panicOnExit || *panicOnExit0 {
m.deps.SetPanicOnExit(false)
}
}

Expand Down