mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
cmd/go: add check for unknown godebug setting
A //go:debug line mentioning an unknown or retired setting should be diagnosed as making the program invalid. Do that. We agreed on this in the proposal but I forgot to implement it. Change-Id: Ie69072a1682d4eeb6866c02adbbb426f608567c4 Reviewed-on: https://go-review.googlesource.com/c/go/+/476280 Run-TryBot: Russ Cox <rsc@golang.org> Reviewed-by: Bryan Mills <bcmills@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
44e51e60ac
commit
14ab998f95
@ -219,7 +219,7 @@ func cloneGOROOTDeps(goroot string) error {
|
|||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
parentFound := false
|
parentFound := false
|
||||||
for _, prev := range pkgRoots {
|
for _, prev := range pkgRoots {
|
||||||
if strings.HasPrefix(pkg, prev) {
|
if pkg == prev || strings.HasPrefix(pkg, prev+"/") {
|
||||||
// We will copy in the source for pkg when we copy in prev.
|
// We will copy in the source for pkg when we copy in prev.
|
||||||
parentFound = true
|
parentFound = true
|
||||||
break
|
break
|
||||||
|
1
src/cmd/dist/buildtool.go
vendored
1
src/cmd/dist/buildtool.go
vendored
@ -65,6 +65,7 @@ var bootstrapDirs = []string{
|
|||||||
"internal/coverage",
|
"internal/coverage",
|
||||||
"internal/buildcfg",
|
"internal/buildcfg",
|
||||||
"internal/goarch",
|
"internal/goarch",
|
||||||
|
"internal/godebugs",
|
||||||
"internal/goexperiment",
|
"internal/goexperiment",
|
||||||
"internal/goroot",
|
"internal/goroot",
|
||||||
"internal/goversion",
|
"internal/goversion",
|
||||||
|
@ -187,7 +187,7 @@ func execGoToolchain(gotoolchain, dir, exe string) {
|
|||||||
// propagate signals and such, but there are no signals on Windows.
|
// propagate signals and such, but there are no signals on Windows.
|
||||||
// We also use the exec case when GODEBUG=gotoolchainexec=0,
|
// We also use the exec case when GODEBUG=gotoolchainexec=0,
|
||||||
// to allow testing this code even when not on Windows.
|
// to allow testing this code even when not on Windows.
|
||||||
if godebug.New("gotoolchainexec").Value() == "0" || runtime.GOOS == "windows" {
|
if godebug.New("#gotoolchainexec").Value() == "0" || runtime.GOOS == "windows" {
|
||||||
cmd := exec.Command(exe, os.Args[1:]...)
|
cmd := exec.Command(exe, os.Args[1:]...)
|
||||||
if runtime.GOOS == "windows" && strings.Contains(exe, "go1.999test") {
|
if runtime.GOOS == "windows" && strings.Contains(exe, "go1.999test") {
|
||||||
// See testdata/script/gotoolchain.txt.
|
// See testdata/script/gotoolchain.txt.
|
||||||
|
@ -48,9 +48,9 @@ var (
|
|||||||
traceFile *os.File
|
traceFile *os.File
|
||||||
traceMu sync.Mutex
|
traceMu sync.Mutex
|
||||||
|
|
||||||
gofsystrace = godebug.New("gofsystrace")
|
gofsystrace = godebug.New("#gofsystrace")
|
||||||
gofsystracelog = godebug.New("gofsystracelog")
|
gofsystracelog = godebug.New("#gofsystracelog")
|
||||||
gofsystracestack = godebug.New("gofsystracestack")
|
gofsystracestack = godebug.New("#gofsystracestack")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
"internal/godebugs"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -43,7 +44,13 @@ func ParseGoDebug(text string) (key, value string, err error) {
|
|||||||
if strings.ContainsAny(v, ",") {
|
if strings.ContainsAny(v, ",") {
|
||||||
return "", "", fmt.Errorf("value contains comma")
|
return "", "", fmt.Errorf("value contains comma")
|
||||||
}
|
}
|
||||||
return k, v, nil
|
|
||||||
|
for _, info := range godebugs.All {
|
||||||
|
if k == info.Name {
|
||||||
|
return k, v, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", "", fmt.Errorf("unknown //go:debug setting %q", k)
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultGODEBUG returns the default GODEBUG setting for the main package p.
|
// defaultGODEBUG returns the default GODEBUG setting for the main package p.
|
||||||
@ -110,19 +117,10 @@ func godebugForGoVersion(v string) map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
def := make(map[string]string)
|
def := make(map[string]string)
|
||||||
for _, d := range defaultGodebugs {
|
for _, info := range godebugs.All {
|
||||||
if (d.before != 0 && n < d.before) || (d.first != 0 && n >= d.first) {
|
if n < info.Changed {
|
||||||
def[d.name] = d.value
|
def[info.Name] = info.Old
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return def
|
return def
|
||||||
}
|
}
|
||||||
|
|
||||||
var defaultGodebugs = []struct {
|
|
||||||
before int // applies to Go versions up until this one (21 for Go 1.21)
|
|
||||||
first int // applies to Go versions starting at this one (21 for Go 1.21)
|
|
||||||
name string
|
|
||||||
value string
|
|
||||||
}{
|
|
||||||
{before: 21, name: "panicnil", value: "1"},
|
|
||||||
}
|
|
||||||
|
@ -37,7 +37,7 @@ import (
|
|||||||
// It will be removed before the release.
|
// It will be removed before the release.
|
||||||
// TODO(matloob): Remove enabled once we have more confidence on the
|
// TODO(matloob): Remove enabled once we have more confidence on the
|
||||||
// module index.
|
// module index.
|
||||||
var enabled = godebug.New("goindex").Value() != "0"
|
var enabled = godebug.New("#goindex").Value() != "0"
|
||||||
|
|
||||||
// Module represents and encoded module index file. It is used to
|
// Module represents and encoded module index file. It is used to
|
||||||
// do the equivalent of build.Import of packages in the module and answer other
|
// do the equivalent of build.Import of packages in the module and answer other
|
||||||
|
9
src/cmd/go/testdata/script/godebug_unknown.txt
vendored
Normal file
9
src/cmd/go/testdata/script/godebug_unknown.txt
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
! go build
|
||||||
|
stderr 'p.go:1:1: invalid //go:debug: unknown //go:debug setting "x"'
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module m
|
||||||
|
-- p.go --
|
||||||
|
//go:debug x=y
|
||||||
|
package main
|
||||||
|
func main() {}
|
@ -42,7 +42,7 @@ var depsRules = `
|
|||||||
< constraints, container/list, container/ring,
|
< constraints, container/list, container/ring,
|
||||||
internal/cfg, internal/coverage, internal/coverage/rtcov,
|
internal/cfg, internal/coverage, internal/coverage/rtcov,
|
||||||
internal/coverage/uleb128, internal/coverage/calloc,
|
internal/coverage/uleb128, internal/coverage/calloc,
|
||||||
internal/cpu, internal/goarch,
|
internal/cpu, internal/goarch, internal/godebugs,
|
||||||
internal/goexperiment, internal/goos,
|
internal/goexperiment, internal/goos,
|
||||||
internal/goversion, internal/nettrace, internal/platform,
|
internal/goversion, internal/nettrace, internal/platform,
|
||||||
log/internal,
|
log/internal,
|
||||||
@ -55,7 +55,7 @@ var depsRules = `
|
|||||||
|
|
||||||
# RUNTIME is the core runtime group of packages, all of them very light-weight.
|
# RUNTIME is the core runtime group of packages, all of them very light-weight.
|
||||||
internal/abi, internal/cpu, internal/goarch,
|
internal/abi, internal/cpu, internal/goarch,
|
||||||
internal/coverage/rtcov, internal/goexperiment,
|
internal/coverage/rtcov, internal/godebugs, internal/goexperiment,
|
||||||
internal/goos, unsafe
|
internal/goos, unsafe
|
||||||
< internal/bytealg
|
< internal/bytealg
|
||||||
< internal/itoa
|
< internal/itoa
|
||||||
|
@ -48,7 +48,7 @@ func TestDisableAllCapabilities(t *testing.T) {
|
|||||||
func TestAllCapabilitiesDisabled(t *testing.T) {
|
func TestAllCapabilitiesDisabled(t *testing.T) {
|
||||||
MustHaveDebugOptionsSupport(t)
|
MustHaveDebugOptionsSupport(t)
|
||||||
|
|
||||||
if godebug.New("cpu.all").Value() != "off" {
|
if godebug.New("#cpu.all").Value() != "off" {
|
||||||
t.Skipf("skipping test: GODEBUG=cpu.all=off not set")
|
t.Skipf("skipping test: GODEBUG=cpu.all=off not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ func TestDisableSSE3(t *testing.T) {
|
|||||||
func TestSSE3DebugOption(t *testing.T) {
|
func TestSSE3DebugOption(t *testing.T) {
|
||||||
MustHaveDebugOptionsSupport(t)
|
MustHaveDebugOptionsSupport(t)
|
||||||
|
|
||||||
if godebug.New("cpu.sse3").Value() != "off" {
|
if godebug.New("#cpu.sse3").Value() != "off" {
|
||||||
t.Skipf("skipping test: GODEBUG=cpu.sse3=off not set")
|
t.Skipf("skipping test: GODEBUG=cpu.sse3=off not set")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1090,7 +1090,7 @@ var zeroVals []any = []any{
|
|||||||
uint64(0),
|
uint64(0),
|
||||||
}
|
}
|
||||||
|
|
||||||
var debugInfo = godebug.New("fuzzdebug").Value() == "1"
|
var debugInfo = godebug.New("#fuzzdebug").Value() == "1"
|
||||||
|
|
||||||
func shouldPrintDebugInfo() bool {
|
func shouldPrintDebugInfo() bool {
|
||||||
return debugInfo
|
return debugInfo
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
package godebug
|
package godebug
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"internal/godebugs"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
_ "unsafe" // go:linkname
|
_ "unsafe" // go:linkname
|
||||||
@ -46,21 +47,38 @@ type setting struct {
|
|||||||
value atomic.Pointer[string]
|
value atomic.Pointer[string]
|
||||||
nonDefaultOnce sync.Once
|
nonDefaultOnce sync.Once
|
||||||
nonDefault atomic.Uint64
|
nonDefault atomic.Uint64
|
||||||
|
info *godebugs.Info
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Setting for the $GODEBUG setting with the given name.
|
// New returns a new Setting for the $GODEBUG setting with the given name.
|
||||||
|
//
|
||||||
|
// GODEBUGs meant for use by end users must be listed in ../godebugs/table.go,
|
||||||
|
// which is used for generating and checking various documentation.
|
||||||
|
// If the name is not listed in that table, New will succeed but calling Value
|
||||||
|
// on the returned Setting will panic.
|
||||||
|
// To disable that panic for access to an undocumented setting,
|
||||||
|
// prefix the name with a #, as in godebug.New("#gofsystrace").
|
||||||
|
// The # is a signal to New but not part of the key used in $GODEBUG.
|
||||||
func New(name string) *Setting {
|
func New(name string) *Setting {
|
||||||
return &Setting{name: name}
|
return &Setting{name: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the name of the setting.
|
// Name returns the name of the setting.
|
||||||
func (s *Setting) Name() string {
|
func (s *Setting) Name() string {
|
||||||
|
if s.name != "" && s.name[0] == '#' {
|
||||||
|
return s.name[1:]
|
||||||
|
}
|
||||||
return s.name
|
return s.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Undocumented reports whether this is an undocumented setting.
|
||||||
|
func (s *Setting) Undocumented() bool {
|
||||||
|
return s.name != "" && s.name[0] == '#'
|
||||||
|
}
|
||||||
|
|
||||||
// String returns a printable form for the setting: name=value.
|
// String returns a printable form for the setting: name=value.
|
||||||
func (s *Setting) String() string {
|
func (s *Setting) String() string {
|
||||||
return s.name + "=" + s.Value()
|
return s.Name() + "=" + s.Value()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncNonDefault increments the non-default behavior counter
|
// IncNonDefault increments the non-default behavior counter
|
||||||
@ -69,20 +87,16 @@ func (s *Setting) String() string {
|
|||||||
// /godebug/non-default-behavior/<name>:events.
|
// /godebug/non-default-behavior/<name>:events.
|
||||||
//
|
//
|
||||||
// Note that Value must be called at least once before IncNonDefault.
|
// Note that Value must be called at least once before IncNonDefault.
|
||||||
//
|
|
||||||
// Any GODEBUG setting that can call IncNonDefault must be listed
|
|
||||||
// in three more places:
|
|
||||||
//
|
|
||||||
// - the table in ../runtime/metrics.go (search for non-default-behavior)
|
|
||||||
// - the table in ../../runtime/metrics/description.go (search for non-default-behavior; run 'go generate' afterward)
|
|
||||||
// - the table in ../../cmd/go/internal/load/godebug.go (search for defaultGodebugs)
|
|
||||||
func (s *Setting) IncNonDefault() {
|
func (s *Setting) IncNonDefault() {
|
||||||
s.nonDefaultOnce.Do(s.register)
|
s.nonDefaultOnce.Do(s.register)
|
||||||
s.nonDefault.Add(1)
|
s.nonDefault.Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Setting) register() {
|
func (s *Setting) register() {
|
||||||
registerMetric("/godebug/non-default-behavior/"+s.name+":events", s.nonDefault.Load)
|
if s.info == nil || s.info.Opaque {
|
||||||
|
panic("godebug: unexpected IncNonDefault of " + s.name)
|
||||||
|
}
|
||||||
|
registerMetric("/godebug/non-default-behavior/"+s.Name()+":events", s.nonDefault.Load)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cache is a cache of all the GODEBUG settings,
|
// cache is a cache of all the GODEBUG settings,
|
||||||
@ -111,7 +125,10 @@ var empty string
|
|||||||
// caching of Value's result.
|
// caching of Value's result.
|
||||||
func (s *Setting) Value() string {
|
func (s *Setting) Value() string {
|
||||||
s.once.Do(func() {
|
s.once.Do(func() {
|
||||||
s.setting = lookup(s.name)
|
s.setting = lookup(s.Name())
|
||||||
|
if s.info == nil && !s.Undocumented() {
|
||||||
|
panic("godebug: Value of name not listed in godebugs.All: " + s.name)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
return *s.value.Load()
|
return *s.value.Load()
|
||||||
}
|
}
|
||||||
@ -122,6 +139,7 @@ func lookup(name string) *setting {
|
|||||||
return v.(*setting)
|
return v.(*setting)
|
||||||
}
|
}
|
||||||
s := new(setting)
|
s := new(setting)
|
||||||
|
s.info = godebugs.Lookup(name)
|
||||||
s.value.Store(&empty)
|
s.value.Store(&empty)
|
||||||
if v, loaded := cache.LoadOrStore(name, s); loaded {
|
if v, loaded := cache.LoadOrStore(name, s); loaded {
|
||||||
// Lost race: someone else created it. Use theirs.
|
// Lost race: someone else created it. Use theirs.
|
||||||
|
@ -11,13 +11,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
foo := New("foo")
|
foo := New("#foo")
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
godebug string
|
godebug string
|
||||||
setting *Setting
|
setting *Setting
|
||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{"", New(""), ""},
|
{"", New("#"), ""},
|
||||||
{"", foo, ""},
|
{"", foo, ""},
|
||||||
{"foo=bar", foo, "bar"},
|
{"foo=bar", foo, "bar"},
|
||||||
{"foo=bar,after=x", foo, "bar"},
|
{"foo=bar,after=x", foo, "bar"},
|
||||||
@ -28,7 +28,7 @@ func TestGet(t *testing.T) {
|
|||||||
{"foo=", foo, ""},
|
{"foo=", foo, ""},
|
||||||
{"foo", foo, ""},
|
{"foo", foo, ""},
|
||||||
{",foo", foo, ""},
|
{",foo", foo, ""},
|
||||||
{"foo=bar,baz", New("loooooooong"), ""},
|
{"foo=bar,baz", New("#loooooooong"), ""},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Setenv("GODEBUG", tt.godebug)
|
t.Setenv("GODEBUG", tt.godebug)
|
||||||
|
41
src/internal/godebugs/godebugs_test.go
Normal file
41
src/internal/godebugs/godebugs_test.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package godebugs_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"internal/godebugs"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAll(t *testing.T) {
|
||||||
|
data, err := os.ReadFile("../../../doc/godebug.md")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
doc := string(data)
|
||||||
|
|
||||||
|
last := ""
|
||||||
|
for _, info := range godebugs.All {
|
||||||
|
if info.Name <= last {
|
||||||
|
t.Errorf("All not sorted: %s then %s", last, info.Name)
|
||||||
|
}
|
||||||
|
last = info.Name
|
||||||
|
|
||||||
|
if info.Package == "" {
|
||||||
|
t.Errorf("Name=%s missing Package", info.Name)
|
||||||
|
}
|
||||||
|
if info.Changed != 0 && info.Old == "" {
|
||||||
|
t.Errorf("Name=%s has Changed, missing Old", info.Name)
|
||||||
|
}
|
||||||
|
if info.Old != "" && info.Changed == 0 {
|
||||||
|
t.Errorf("Name=%s has Old, missing Changed", info.Name)
|
||||||
|
}
|
||||||
|
if !strings.Contains(doc, "`"+info.Name+"`") {
|
||||||
|
t.Errorf("Name=%s not documented in doc/godebug.md", info.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
64
src/internal/godebugs/table.go
Normal file
64
src/internal/godebugs/table.go
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package godebugs provides a table of known GODEBUG settings,
|
||||||
|
// for use by a variety of other packages, including internal/godebug,
|
||||||
|
// runtime, runtime/metrics, and cmd/go/internal/load.
|
||||||
|
package godebugs
|
||||||
|
|
||||||
|
// An Info describes a single known GODEBUG setting.
|
||||||
|
type Info struct {
|
||||||
|
Name string // name of the setting ("panicnil")
|
||||||
|
Package string // package that uses the setting ("runtime")
|
||||||
|
Changed int // minor version when default changed, if any; 21 means Go 1.21
|
||||||
|
Old string // value that restores behavior prior to Changed
|
||||||
|
Opaque bool // setting does not export information to runtime/metrics using [internal/godebug.Setting.IncNonDefault]
|
||||||
|
}
|
||||||
|
|
||||||
|
// All is the table of known settings, sorted by Name.
|
||||||
|
//
|
||||||
|
// Note: After adding entries to this table, run 'go generate runtime/metrics'
|
||||||
|
// to update the runtime/metrics doc comment.
|
||||||
|
// (Otherwise the runtime/metrics test will fail.)
|
||||||
|
//
|
||||||
|
// Note: After adding entries to this table, update the list in doc/godebug.md as well.
|
||||||
|
// (Otherwise the test in this package will fail.)
|
||||||
|
var All = []Info{
|
||||||
|
{Name: "execerrdot", Package: "os/exec"},
|
||||||
|
{Name: "http2client", Package: "net/http"},
|
||||||
|
{Name: "http2debug", Package: "net/http", Opaque: true},
|
||||||
|
{Name: "http2server", Package: "net/http"},
|
||||||
|
{Name: "installgoroot", Package: "go/build"},
|
||||||
|
{Name: "jstmpllitinterp", Package: "html/template"},
|
||||||
|
//{Name: "multipartfiles", Package: "mime/multipart"},
|
||||||
|
{Name: "multipartmaxheaders", Package: "mime/multipart"},
|
||||||
|
{Name: "multipartmaxparts", Package: "mime/multipart"},
|
||||||
|
{Name: "netdns", Package: "net", Opaque: true},
|
||||||
|
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
|
||||||
|
{Name: "randautoseed", Package: "math/rand"},
|
||||||
|
{Name: "tarinsecurepath", Package: "archive/tar"},
|
||||||
|
{Name: "x509sha1", Package: "crypto/x509"},
|
||||||
|
{Name: "x509usefallbackroots", Package: "crypto/x509"},
|
||||||
|
{Name: "zipinsecurepath", Package: "archive/zip"},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup returns the Info with the given name.
|
||||||
|
func Lookup(name string) *Info {
|
||||||
|
// binary search, avoiding import of sort.
|
||||||
|
lo := 0
|
||||||
|
hi := len(All)
|
||||||
|
for lo < hi {
|
||||||
|
m := lo + (hi-lo)>>1
|
||||||
|
mid := All[m].Name
|
||||||
|
if name == mid {
|
||||||
|
return &All[m]
|
||||||
|
}
|
||||||
|
if name < mid {
|
||||||
|
hi = m
|
||||||
|
} else {
|
||||||
|
lo = m + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -66,7 +66,7 @@ var (
|
|||||||
valSafe = safeMap() // non-nil in safe+leaky mode
|
valSafe = safeMap() // non-nil in safe+leaky mode
|
||||||
)
|
)
|
||||||
|
|
||||||
var intern = godebug.New("intern")
|
var intern = godebug.New("#intern")
|
||||||
|
|
||||||
// safeMap returns a non-nil map if we're in safe-but-leaky mode,
|
// safeMap returns a non-nil map if we're in safe-but-leaky mode,
|
||||||
// as controlled by GODEBUG=intern=leaky
|
// as controlled by GODEBUG=intern=leaky
|
||||||
|
@ -34,7 +34,7 @@ func (r *Reader) ReadForm(maxMemory int64) (*Form, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
multipartFiles = godebug.New("multipartfiles")
|
multipartFiles = godebug.New("#multipartfiles") // TODO: document and remove #
|
||||||
multipartMaxParts = godebug.New("multipartmaxparts")
|
multipartMaxParts = godebug.New("multipartmaxparts")
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ func (r *Reader) readForm(maxMemory int64) (_ *Form, err error) {
|
|||||||
combineFiles := true
|
combineFiles := true
|
||||||
if multipartFiles.Value() == "distinct" {
|
if multipartFiles.Value() == "distinct" {
|
||||||
combineFiles = false
|
combineFiles = false
|
||||||
multipartFiles.IncNonDefault()
|
// multipartFiles.IncNonDefault() // TODO: uncomment after documenting
|
||||||
}
|
}
|
||||||
maxParts := 1000
|
maxParts := 1000
|
||||||
if s := multipartMaxParts.Value(); s != "" {
|
if s := multipartMaxParts.Value(); s != "" {
|
||||||
|
@ -348,7 +348,7 @@ type ctxResult struct {
|
|||||||
timer *time.Timer
|
timer *time.Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
var execwait = godebug.New("execwait")
|
var execwait = godebug.New("#execwait")
|
||||||
var execerrdot = godebug.New("execerrdot")
|
var execerrdot = godebug.New("execerrdot")
|
||||||
|
|
||||||
// Command returns the Cmd struct to execute the named program with
|
// Command returns the Cmd struct to execute the named program with
|
||||||
|
@ -7,6 +7,7 @@ package runtime
|
|||||||
// Metrics implementation exported to runtime/metrics.
|
// Metrics implementation exported to runtime/metrics.
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"internal/godebugs"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -286,20 +287,6 @@ func initMetrics() {
|
|||||||
out.scalar = uint64(startingStackSize)
|
out.scalar = uint64(startingStackSize)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"/godebug/non-default-behavior/execerrdot:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/http2client:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/http2server:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/installgoroot:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/jstmpllitinterp:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/multipartfiles:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/multipartmaxheaders:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/multipartmaxparts:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/panicnil:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/randautoseed:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/tarinsecurepath:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/x509sha1:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/x509usefallbackroots:events": {compute: compute0},
|
|
||||||
"/godebug/non-default-behavior/zipinsecurepath:events": {compute: compute0},
|
|
||||||
"/memory/classes/heap/free:bytes": {
|
"/memory/classes/heap/free:bytes": {
|
||||||
deps: makeStatDepSet(heapStatsDep),
|
deps: makeStatDepSet(heapStatsDep),
|
||||||
compute: func(in *statAggregate, out *metricValue) {
|
compute: func(in *statAggregate, out *metricValue) {
|
||||||
@ -432,6 +419,13 @@ func initMetrics() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, info := range godebugs.All {
|
||||||
|
if !info.Opaque {
|
||||||
|
metrics["/godebug/non-default-behavior/"+info.Name+":events"] = metricData{compute: compute0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
metricsInit = true
|
metricsInit = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,10 +441,6 @@ func (f metricReader) compute(_ *statAggregate, out *metricValue) {
|
|||||||
out.scalar = f()
|
out.scalar = f()
|
||||||
}
|
}
|
||||||
|
|
||||||
var godebugNonDefaults = []string{
|
|
||||||
"panicnil",
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:linkname godebug_registerMetric internal/godebug.registerMetric
|
//go:linkname godebug_registerMetric internal/godebug.registerMetric
|
||||||
func godebug_registerMetric(name string, read func() uint64) {
|
func godebug_registerMetric(name string, read func() uint64) {
|
||||||
metricsLock()
|
metricsLock()
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
package metrics
|
package metrics
|
||||||
|
|
||||||
|
import "internal/godebugs"
|
||||||
|
|
||||||
// Description describes a runtime metric.
|
// Description describes a runtime metric.
|
||||||
type Description struct {
|
type Description struct {
|
||||||
// Name is the full name of the metric which includes the unit.
|
// Name is the full name of the metric which includes the unit.
|
||||||
@ -49,7 +51,7 @@ type Description struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The English language descriptions below must be kept in sync with the
|
// The English language descriptions below must be kept in sync with the
|
||||||
// descriptions of each metric in doc.go.
|
// descriptions of each metric in doc.go by running 'go generate'.
|
||||||
var allDesc = []Description{
|
var allDesc = []Description{
|
||||||
{
|
{
|
||||||
Name: "/cgo/go-to-c-calls:calls",
|
Name: "/cgo/go-to-c-calls:calls",
|
||||||
@ -277,104 +279,6 @@ var allDesc = []Description{
|
|||||||
Kind: KindUint64,
|
Kind: KindUint64,
|
||||||
Cumulative: false,
|
Cumulative: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/execerrdot:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the os/exec package " +
|
|
||||||
"due to a non-default GODEBUG=execerrdot=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/http2client:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the net/http package " +
|
|
||||||
"due to a non-default GODEBUG=http2client=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/http2server:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the net/http package " +
|
|
||||||
"due to a non-default GODEBUG=http2server=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/installgoroot:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the go/build package " +
|
|
||||||
"due to a non-default GODEBUG=installgoroot=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/jstmpllitinterp:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the html/template" +
|
|
||||||
"package due to a non-default GODEBUG=jstmpllitinterp=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/multipartfiles:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the mime/multipart package " +
|
|
||||||
"due to a non-default GODEBUG=multipartfiles=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/multipartmaxheaders:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the mime/multipart package " +
|
|
||||||
"due to a non-default GODEBUG=multipartmaxheaders=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/multipartmaxparts:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the mime/multipart package " +
|
|
||||||
"due to a non-default GODEBUG=multipartmaxparts=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/panicnil:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the runtime package " +
|
|
||||||
"due to a non-default GODEBUG=panicnil=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/randautoseed:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the math/rand package " +
|
|
||||||
"due to a non-default GODEBUG=randautoseed=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/tarinsecurepath:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the archive/tar package " +
|
|
||||||
"due to a non-default GODEBUG=tarinsecurepath=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/x509sha1:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the crypto/x509 package " +
|
|
||||||
"due to a non-default GODEBUG=x509sha1=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/x509usefallbackroots:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the crypto/x509 package " +
|
|
||||||
"due to a non-default GODEBUG=x509usefallbackroots=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "/godebug/non-default-behavior/zipinsecurepath:events",
|
|
||||||
Description: "The number of non-default behaviors executed by the archive/zip package " +
|
|
||||||
"due to a non-default GODEBUG=zipinsecurepath=... setting.",
|
|
||||||
Kind: KindUint64,
|
|
||||||
Cumulative: true,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "/memory/classes/heap/free:bytes",
|
Name: "/memory/classes/heap/free:bytes",
|
||||||
Description: "Memory that is completely free and eligible to be returned to the underlying system, " +
|
Description: "Memory that is completely free and eligible to be returned to the underlying system, " +
|
||||||
@ -472,6 +376,30 @@ var allDesc = []Description{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// Insert all the the non-default-reporting GODEBUGs into the table,
|
||||||
|
// preserving the overall sort order.
|
||||||
|
i := 0
|
||||||
|
for i < len(allDesc) && allDesc[i].Name < "/godebug/" {
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
more := make([]Description, i, len(allDesc)+len(godebugs.All))
|
||||||
|
copy(more, allDesc)
|
||||||
|
for _, info := range godebugs.All {
|
||||||
|
if !info.Opaque {
|
||||||
|
more = append(more, Description{
|
||||||
|
Name: "/godebug/non-default-behavior/" + info.Name + ":events",
|
||||||
|
Description: "The number of non-default behaviors executed by the " +
|
||||||
|
info.Package + " package " + "due to a non-default " +
|
||||||
|
"GODEBUG=" + info.Name + "=... setting.",
|
||||||
|
Kind: KindUint64,
|
||||||
|
Cumulative: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allDesc = append(more, allDesc[i:]...)
|
||||||
|
}
|
||||||
|
|
||||||
// All returns a slice of containing metric descriptions for all supported metrics.
|
// All returns a slice of containing metric descriptions for all supported metrics.
|
||||||
func All() []Description {
|
func All() []Description {
|
||||||
return allDesc
|
return allDesc
|
||||||
|
@ -221,14 +221,9 @@ Below is the full list of supported metrics, ordered lexicographically.
|
|||||||
|
|
||||||
/godebug/non-default-behavior/jstmpllitinterp:events
|
/godebug/non-default-behavior/jstmpllitinterp:events
|
||||||
The number of non-default behaviors executed by
|
The number of non-default behaviors executed by
|
||||||
the html/templatepackage due to a non-default
|
the html/template package due to a non-default
|
||||||
GODEBUG=jstmpllitinterp=... setting.
|
GODEBUG=jstmpllitinterp=... setting.
|
||||||
|
|
||||||
/godebug/non-default-behavior/multipartfiles:events
|
|
||||||
The number of non-default behaviors executed by
|
|
||||||
the mime/multipart package due to a non-default
|
|
||||||
GODEBUG=multipartfiles=... setting.
|
|
||||||
|
|
||||||
/godebug/non-default-behavior/multipartmaxheaders:events
|
/godebug/non-default-behavior/multipartmaxheaders:events
|
||||||
The number of non-default behaviors executed by
|
The number of non-default behaviors executed by
|
||||||
the mime/multipart package due to a non-default
|
the mime/multipart package due to a non-default
|
||||||
|
Loading…
x
Reference in New Issue
Block a user