From 4f77a83589baa5a3038cc6e35615084dc7e5f0c1 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Thu, 30 May 2024 14:31:40 -0700 Subject: [PATCH 01/72] internal/syscall/unix: fix UTIME_OMIT for dragonfly CL 219638 added UTIME_OMIT values for various systems. The value for DragonFly BSD appears to be incorrect. The correct value is -2 (see references below), while -1 is used for UTIME_NOW. As a result, timestamp is changed to the current time instead of not touching. This should have been caught by the accompanying test case, TestChtimesWithZeroTimes, but its failures are essentially skipped on dragonfly (this is being fixed separately in a followup CL 591535). Improve formatting while at it. References: - https://github.com/DragonFlyBSD/DragonFlyBSD/blob/965b380e9609/sys/sys/stat.h#L284 - https://go.googlesource.com/sys/+/refs/tags/v0.20.0/unix/zerrors_dragonfly_amd64.go#1421 Change-Id: I432360ca982c84b7cd70d0cf01d860af9ff985fa Reviewed-on: https://go-review.googlesource.com/c/go/+/589496 LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Commit-Queue: Ian Lance Taylor --- src/internal/syscall/unix/at_sysnum_dragonfly.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/internal/syscall/unix/at_sysnum_dragonfly.go b/src/internal/syscall/unix/at_sysnum_dragonfly.go index 9ac1f919f1..a8164dcc8e 100644 --- a/src/internal/syscall/unix/at_sysnum_dragonfly.go +++ b/src/internal/syscall/unix/at_sysnum_dragonfly.go @@ -6,15 +6,15 @@ package unix import "syscall" -const unlinkatTrap uintptr = syscall.SYS_UNLINKAT -const openatTrap uintptr = syscall.SYS_OPENAT -const fstatatTrap uintptr = syscall.SYS_FSTATAT - const ( + unlinkatTrap uintptr = syscall.SYS_UNLINKAT + openatTrap uintptr = syscall.SYS_OPENAT + fstatatTrap uintptr = syscall.SYS_FSTATAT + AT_EACCESS = 0x4 AT_FDCWD = 0xfffafdcd AT_REMOVEDIR = 0x2 AT_SYMLINK_NOFOLLOW = 0x1 - UTIME_OMIT = -0x1 + UTIME_OMIT = -0x2 ) From 477ad7dd5151a2cb54fb68aa84ccbe9bb96ffbee Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 20 Jun 2024 22:58:24 +0700 Subject: [PATCH 02/72] cmd/compile: support generic alias type Type parameters on aliases are now allowed after #46477 accepted. Updates #46477 Fixes #68054 Change-Id: Ic2e3b6f960a898163f47666e3a6bfe43b8cc22e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/593715 Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky LUCI-TryBot-Result: Go LUCI Auto-Submit: Robert Griesemer --- src/cmd/compile/internal/noder/writer.go | 13 ++++++++++++- test/fixedbugs/issue68054.go | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue68054.go diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 9b33fb7c6d..fe8f8f2a35 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -543,7 +543,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { case *types2.Alias: w.Code(pkgbits.TypeNamed) - w.namedType(typ.Obj(), nil) + w.namedType(splitAlias(typ)) case *types2.TypeParam: w.derived = true @@ -2958,6 +2958,9 @@ func objTypeParams(obj types2.Object) *types2.TypeParamList { if !obj.IsAlias() { return obj.Type().(*types2.Named).TypeParams() } + if alias, ok := obj.Type().(*types2.Alias); ok { + return alias.TypeParams() + } } return nil } @@ -2974,6 +2977,14 @@ func splitNamed(typ *types2.Named) (*types2.TypeName, *types2.TypeList) { return typ.Obj(), typ.TypeArgs() } +// splitAlias is like splitNamed, but for an alias type. +func splitAlias(typ *types2.Alias) (*types2.TypeName, *types2.TypeList) { + orig := typ.Origin() + base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj()) + + return typ.Obj(), typ.TypeArgs() +} + func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { if p == nil { return 0 diff --git a/test/fixedbugs/issue68054.go b/test/fixedbugs/issue68054.go new file mode 100644 index 0000000000..5409fc9081 --- /dev/null +++ b/test/fixedbugs/issue68054.go @@ -0,0 +1,23 @@ +// compile -goexperiment aliastypeparams + +// Copyright 2024 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 p + +type Seq[V any] = func(yield func(V) bool) + +func f[E any](seq Seq[E]) { + return +} + +func g() { + f(Seq[int](nil)) +} + +type T[P any] struct{} + +type A[P any] = T[P] + +var _ A[int] From 9d33956503c0d96c0c5666d374173f7ac9756d98 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Thu, 20 Jun 2024 10:23:42 -0700 Subject: [PATCH 03/72] internal/godebugs: fix old value for httpservecontentkeepheaders The pre-Go 1.23 behavior is httpservecontentkeepheaders=1. For #66343 Change-Id: If6f92853b38522f19a8908ff11ac49b12f3dc3e0 Reviewed-on: https://go-review.googlesource.com/c/go/+/593775 Reviewed-by: David Chase Auto-Submit: Damien Neil LUCI-TryBot-Result: Go LUCI --- src/internal/godebugs/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index f4262b6695..4c084635fb 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -36,7 +36,7 @@ var All = []Info{ {Name: "http2server", Package: "net/http"}, {Name: "httplaxcontentlength", Package: "net/http", Changed: 22, Old: "1"}, {Name: "httpmuxgo121", Package: "net/http", Changed: 22, Old: "1"}, - {Name: "httpservecontentkeepheaders", Package: "net/http", Changed: 23, Old: "0"}, + {Name: "httpservecontentkeepheaders", Package: "net/http", Changed: 23, Old: "1"}, {Name: "installgoroot", Package: "go/build"}, {Name: "jstmpllitinterp", Package: "html/template", Opaque: true}, // bug #66217: remove Opaque //{Name: "multipartfiles", Package: "mime/multipart"}, From 20b79fd5775c39061d949569743912ad5e58b0e7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 2 May 2024 14:29:16 -0400 Subject: [PATCH 04/72] time: provide non-default metric for asynctimerchan The original implementation could not support a non-default metric, but now that it is set during package time, we can. Do that. Change-Id: If7929b0afa5b0142d299718d9bd811c5a8d1cf93 Reviewed-on: https://go-review.googlesource.com/c/go/+/589058 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- src/internal/godebugs/table.go | 2 +- src/runtime/metrics/doc.go | 4 ++++ src/time/sleep.go | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index 4c084635fb..a802ac9c37 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -25,7 +25,7 @@ type Info struct { // 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: "asynctimerchan", Package: "time", Changed: 23, Old: "1", Opaque: true}, + {Name: "asynctimerchan", Package: "time", Changed: 23, Old: "1"}, {Name: "execerrdot", Package: "os/exec"}, {Name: "gocachehash", Package: "cmd/go"}, {Name: "gocachetest", Package: "cmd/go"}, diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index b8be9f8272..da3d956d48 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -230,6 +230,10 @@ Below is the full list of supported metrics, ordered lexicographically. /gc/stack/starting-size:bytes The stack size of new goroutines. + /godebug/non-default-behavior/asynctimerchan:events + The number of non-default behaviors executed by the time package + due to a non-default GODEBUG=asynctimerchan=... setting. + /godebug/non-default-behavior/execerrdot:events The number of non-default behaviors executed by the os/exec package due to a non-default GODEBUG=execerrdot=... setting. diff --git a/src/time/sleep.go b/src/time/sleep.go index 2c6495d93a..7e2fa0c20a 100644 --- a/src/time/sleep.go +++ b/src/time/sleep.go @@ -23,6 +23,7 @@ func syncTimer(c chan Time) unsafe.Pointer { // If asynctimerchan=1, we don't even tell the runtime // about channel timers, so that we get the pre-Go 1.23 code paths. if asynctimerchan.Value() == "1" { + asynctimerchan.IncNonDefault() return nil } From 201129414ffc72ce05c170ef2a4627768e890f24 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 18 Jun 2024 22:12:35 -0400 Subject: [PATCH 05/72] sync/atomic: correct result names for Or methods A few of the new Or methods of the atomic types use "new" as the name for the result value, but it actually returns the old value. Fix this by renaming the result values to "old". Updates #61395. Change-Id: Ib08db9964f5dfe91929f216d50ff0c9cc891ee49 Reviewed-on: https://go-review.googlesource.com/c/go/+/593855 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Auto-Submit: Austin Clements Reviewed-by: Mauri de Souza Meneguzzo --- src/sync/atomic/type.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sync/atomic/type.go b/src/sync/atomic/type.go index 7d2b6805bc..f487cb9c5f 100644 --- a/src/sync/atomic/type.go +++ b/src/sync/atomic/type.go @@ -156,7 +156,7 @@ func (x *Uint32) And(mask uint32) (old uint32) { return AndUint32(&x.v, mask) } // Or atomically performs a bitwise OR operation on x using the bitmask // provided as mask and returns the old value. -func (x *Uint32) Or(mask uint32) (new uint32) { return OrUint32(&x.v, mask) } +func (x *Uint32) Or(mask uint32) (old uint32) { return OrUint32(&x.v, mask) } // A Uint64 is an atomic uint64. The zero value is zero. type Uint64 struct { @@ -188,7 +188,7 @@ func (x *Uint64) And(mask uint64) (old uint64) { return AndUint64(&x.v, mask) } // Or atomically performs a bitwise OR operation on x using the bitmask // provided as mask and returns the old value. -func (x *Uint64) Or(mask uint64) (new uint64) { return OrUint64(&x.v, mask) } +func (x *Uint64) Or(mask uint64) (old uint64) { return OrUint64(&x.v, mask) } // A Uintptr is an atomic uintptr. The zero value is zero. type Uintptr struct { From d67839f58af518bfa32e27962059291362186e1c Mon Sep 17 00:00:00 2001 From: Clide Stefani Date: Thu, 13 Jun 2024 14:57:12 -0400 Subject: [PATCH 06/72] crypto/tls: add support for -expect-version to bogo_shim_test The existing implementation of bogo_shim_test does not support tests that use the expect-version flag. This change adds support for this flag. Updates #51434. Change-Id: Ie23fdb06d15ec0593ca58f28144e83f93ef7f200 Reviewed-on: https://go-review.googlesource.com/c/go/+/592635 Auto-Submit: Roland Shoemaker LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker Reviewed-by: David Chase --- src/crypto/tls/bogo_shim_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/crypto/tls/bogo_shim_test.go b/src/crypto/tls/bogo_shim_test.go index 5dc3b7c13e..2d8100d1bb 100644 --- a/src/crypto/tls/bogo_shim_test.go +++ b/src/crypto/tls/bogo_shim_test.go @@ -33,8 +33,9 @@ var ( trustCert = flag.String("trust-cert", "", "") - minVersion = flag.Int("min-version", VersionSSL30, "") - maxVersion = flag.Int("max-version", VersionTLS13, "") + minVersion = flag.Int("min-version", VersionSSL30, "") + maxVersion = flag.Int("max-version", VersionTLS13, "") + expectVersion = flag.Int("expect-version", 0, "") noTLS13 = flag.Bool("no-tls13", false, "") @@ -252,7 +253,9 @@ func bogoShim() { if *expectALPN != "" && cs.NegotiatedProtocol != *expectALPN { log.Fatalf("unexpected protocol negotiated: want %q, got %q", *expectALPN, cs.NegotiatedProtocol) } - + if *expectVersion != 0 && cs.Version != uint16(*expectVersion) { + log.Fatalf("expected ssl version %q, got %q", uint16(*expectVersion), cs.Version) + } if *expectECHAccepted && !cs.ECHAccepted { log.Fatal("expected ECH to be accepted, but connection state shows it was not") } else if i == 0 && *onInitialExpectECHAccepted && !cs.ECHAccepted { From 6fea4094242fe4e7be8bd7ec0b55df9f6df3f025 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 14 Jun 2024 09:48:09 +1000 Subject: [PATCH 07/72] text/template/parse: fix handling of assignment/declaration in PipeNode.String The String method for Pipes assumed all variables were declared. Easy fix: check the IsAssign bit. Fixes #65382 Change-Id: I58f2760c1a8bb2821c3538645d893f58fd76ae73 Reviewed-on: https://go-review.googlesource.com/c/go/+/592695 Run-TryBot: Rob Pike Reviewed-by: David Chase Reviewed-by: Ian Lance Taylor Auto-Submit: Rob Pike TryBot-Result: Gopher Robot LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor --- src/text/template/parse/node.go | 6 +++++- src/text/template/parse/parse_test.go | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go index 23ba9aec2b..a31309874d 100644 --- a/src/text/template/parse/node.go +++ b/src/text/template/parse/node.go @@ -217,7 +217,11 @@ func (p *PipeNode) writeTo(sb *strings.Builder) { } v.writeTo(sb) } - sb.WriteString(" := ") + if p.IsAssign { + sb.WriteString(" = ") + } else { + sb.WriteString(" := ") + } } for i, c := range p.Cmds { if i > 0 { diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go index faf226d1c3..26aff330fe 100644 --- a/src/text/template/parse/parse_test.go +++ b/src/text/template/parse/parse_test.go @@ -306,6 +306,9 @@ var parseTests = []parseTest{ {"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here. {"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2). {"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space. + // Check the range handles assignment vs. declaration properly. + {"bug2a", "{{range $x := 0}}{{$x}}{{end}}", noError, "{{range $x := 0}}{{$x}}{{end}}"}, + {"bug2b", "{{range $x = 0}}{{$x}}{{end}}", noError, "{{range $x = 0}}{{$x}}{{end}}"}, // dot following a literal value {"dot after integer", "{{1.E}}", hasError, ""}, {"dot after float", "{{0.1.E}}", hasError, ""}, From e9a306e004fb6e9c6ca6045151be0ca8bddd242b Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 21 Jun 2024 14:45:26 +0700 Subject: [PATCH 08/72] types2, go/types: correct NewTypeParam documentation Signature type does not have SetTypeParams method, only Named type. Change-Id: Ic7a25c24cb821540d921eb2c94dfff31f28f7aa4 Reviewed-on: https://go-review.googlesource.com/c/go/+/593955 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Findley Auto-Submit: Cuong Manh Le --- src/cmd/compile/internal/types2/typeparam.go | 4 ++-- src/go/types/typeparam.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 9ad064906f..e22981e1ad 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -25,8 +25,8 @@ type TypeParam struct { } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named -// or Signature type by calling SetTypeParams. Setting a type parameter on more -// than one type will result in a panic. +// type by calling SetTypeParams. Setting a type parameter on more than one type +// will result in a panic. // // The constraint argument can be nil, and set later via SetConstraint. If the // constraint is non-nil, it must be fully defined. diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 58a02de860..789b63d7a1 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -28,8 +28,8 @@ type TypeParam struct { } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named -// or Signature type by calling SetTypeParams. Setting a type parameter on more -// than one type will result in a panic. +// type by calling SetTypeParams. Setting a type parameter on more than one type +// will result in a panic. // // The constraint argument can be nil, and set later via SetConstraint. If the // constraint is non-nil, it must be fully defined. From 72e2220b50db5179ddca2226a64bf1d3aa94f49a Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Tue, 18 Jun 2024 23:43:21 +0800 Subject: [PATCH 09/72] encoding/json: clarify the map's key type for Unmarshal While here, also fix doc link for encoding.TextMarshaler. Fixes #67495 Change-Id: Ia2a674c5c35b5a849ce8f5eef3d34d165b3195b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/593335 LUCI-TryBot-Result: Go LUCI Reviewed-by: Joseph Tsai Reviewed-by: David Chase Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor --- src/encoding/json/decode.go | 3 +-- src/encoding/json/encode.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go index efceecdf82..f8205704e3 100644 --- a/src/encoding/json/decode.go +++ b/src/encoding/json/decode.go @@ -73,8 +73,7 @@ import ( // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal // reuses the existing map, keeping existing entries. Unmarshal then stores // key-value pairs from the JSON object into the map. The map's key type must -// either be any string type, an integer, implement [json.Unmarshaler], or -// implement [encoding.TextUnmarshaler]. +// either be any string type, an integer, or implement [encoding.TextUnmarshaler]. // // If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError]. // diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index cb28feb279..7bee1a6805 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -141,7 +141,7 @@ import ( // are sorted and used as JSON object keys by applying the following rules, // subject to the UTF-8 coercion described for string values above: // - keys of any string type are used directly -// - [encoding.TextMarshalers] are marshaled +// - keys that implement [encoding.TextMarshaler] are marshaled // - integer keys are converted to strings // // Pointer values encode as the value pointed to. From 1b4f1dc95d221c1e9d0afb9067fd6a09f12dd061 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 11 Jun 2024 17:25:06 -0700 Subject: [PATCH 10/72] os: improve newFile, rm newDir 1. Assuming that CI environments do not use NFS (and if they do, they have TMPDIR set pointing to a local file system), we can - remove localTmp; - remove newDir, replacing calls to it with t.TempDir; - remove repeated comments about NFS. 2. Use t.Name, t.Cleanup and t.Helper to improve newFile and simplify its usage. Ensure the cleanup reports all errors. Change-Id: I0a79a6a3d52faa323ed2658ef73f8802847f3c09 Reviewed-on: https://go-review.googlesource.com/c/go/+/592096 Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Run-TryBot: Kirill Kolyshkin Reviewed-by: David Chase Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/os/os_test.go | 101 +++++++++++------------------------------ src/os/os_unix_test.go | 30 ++---------- 2 files changed, 32 insertions(+), 99 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index 7348a9f01c..2a6b1bf9f5 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -158,28 +158,20 @@ func equal(name1, name2 string) (r bool) { return } -// localTmp returns a local temporary directory not on NFS. -func localTmp() string { - switch runtime.GOOS { - case "android", "ios", "windows": - return TempDir() - } - return "/tmp" -} - -func newFile(testName string, t *testing.T) (f *File) { - f, err := CreateTemp(localTmp(), "_Go_"+testName) +func newFile(t *testing.T) (f *File) { + t.Helper() + f, err := CreateTemp("", "_Go_"+t.Name()) if err != nil { - t.Fatalf("TempFile %s: %s", testName, err) - } - return -} - -func newDir(testName string, t *testing.T) (name string) { - name, err := MkdirTemp(localTmp(), "_Go_"+testName) - if err != nil { - t.Fatalf("TempDir %s: %s", testName, err) + t.Fatal(err) } + t.Cleanup(func() { + if err := f.Close(); err != nil && !errors.Is(err, ErrClosed) { + t.Fatal(err) + } + if err := Remove(f.Name()); err != nil { + t.Fatal(err) + } + }) return } @@ -1276,9 +1268,7 @@ func TestChmod(t *testing.T) { } t.Parallel() - f := newFile("TestChmod", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) // Creation mode is read write fm := FileMode(0456) @@ -1314,9 +1304,7 @@ func checkSize(t *testing.T, f *File, size int64) { func TestFTruncate(t *testing.T) { t.Parallel() - f := newFile("TestFTruncate", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) checkSize(t, f, 0) f.Write([]byte("hello, world\n")) @@ -1336,9 +1324,7 @@ func TestFTruncate(t *testing.T) { func TestTruncate(t *testing.T) { t.Parallel() - f := newFile("TestTruncate", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) checkSize(t, f, 0) f.Write([]byte("hello, world\n")) @@ -1375,15 +1361,10 @@ func TestTruncateNonexistentFile(t *testing.T) { assertPathError(t, path, err) } -// Use TempDir (via newFile) to make sure we're on a local file system, -// so that timings are not distorted by latency and caching. -// On NFS, timings can be off due to caching of meta-data on -// NFS servers (Issue 848). func TestChtimes(t *testing.T) { t.Parallel() - f := newFile("TestChtimes", t) - defer Remove(f.Name()) + f := newFile(t) f.Write([]byte("hello, world\n")) f.Close() @@ -1392,13 +1373,12 @@ func TestChtimes(t *testing.T) { } func TestChtimesWithZeroTimes(t *testing.T) { - file := newFile("chtimes-with-zero", t) + file := newFile(t) _, err := file.Write([]byte("hello, world\n")) if err != nil { t.Fatalf("Write: %s", err) } fName := file.Name() - defer Remove(file.Name()) err = file.Close() if err != nil { t.Errorf("%v", err) @@ -1513,17 +1493,10 @@ func TestChtimesWithZeroTimes(t *testing.T) { } } -// Use TempDir (via newDir) to make sure we're on a local file system, -// so that timings are not distorted by latency and caching. -// On NFS, timings can be off due to caching of meta-data on -// NFS servers (Issue 848). func TestChtimesDir(t *testing.T) { t.Parallel() - name := newDir("TestChtimes", t) - defer RemoveAll(name) - - testChtimes(t, name) + testChtimes(t, t.TempDir()) } func testChtimes(t *testing.T, name string) { @@ -1574,9 +1547,8 @@ func testChtimes(t *testing.T, name string) { } func TestChtimesToUnixZero(t *testing.T) { - file := newFile("chtimes-to-unix-zero", t) + file := newFile(t) fn := file.Name() - defer Remove(fn) if _, err := file.Write([]byte("hi")); err != nil { t.Fatal(err) } @@ -1796,9 +1768,7 @@ func TestProgWideChdir(t *testing.T) { func TestSeek(t *testing.T) { t.Parallel() - f := newFile("TestSeek", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2040,9 +2010,7 @@ func TestHostname(t *testing.T) { func TestReadAt(t *testing.T) { t.Parallel() - f := newFile("TestReadAt", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2064,9 +2032,7 @@ func TestReadAt(t *testing.T) { func TestReadAtOffset(t *testing.T) { t.Parallel() - f := newFile("TestReadAtOffset", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2095,9 +2061,7 @@ func TestReadAtOffset(t *testing.T) { func TestReadAtNegativeOffset(t *testing.T) { t.Parallel() - f := newFile("TestReadAtNegativeOffset", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2116,9 +2080,7 @@ func TestReadAtNegativeOffset(t *testing.T) { func TestWriteAt(t *testing.T) { t.Parallel() - f := newFile("TestWriteAt", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2141,9 +2103,7 @@ func TestWriteAt(t *testing.T) { func TestWriteAtNegativeOffset(t *testing.T) { t.Parallel() - f := newFile("TestWriteAtNegativeOffset", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) n, err := f.WriteAt([]byte("WORLD"), -10) @@ -2477,9 +2437,7 @@ func TestStatRelativeSymlink(t *testing.T) { func TestReadAtEOF(t *testing.T) { t.Parallel() - f := newFile("TestReadAtEOF", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) _, err := f.ReadAt(make([]byte, 10), 0) switch err { @@ -2495,12 +2453,7 @@ func TestReadAtEOF(t *testing.T) { func TestLongPath(t *testing.T) { t.Parallel() - tmpdir := newDir("TestLongPath", t) - defer func(d string) { - if err := RemoveAll(d); err != nil { - t.Fatalf("RemoveAll failed: %v", err) - } - }(tmpdir) + tmpdir := t.TempDir() // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted). sizes := []int{247, 248, 249, 400} diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 98e436fae6..6cbeae1b78 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -45,13 +45,7 @@ func TestChown(t *testing.T) { } t.Parallel() - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestChown", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) dir, err := f.Stat() if err != nil { t.Fatalf("stat %s: %s", f.Name(), err) @@ -99,13 +93,7 @@ func TestFileChown(t *testing.T) { } t.Parallel() - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestFileChown", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) dir, err := f.Stat() if err != nil { t.Fatalf("stat %s: %s", f.Name(), err) @@ -151,13 +139,7 @@ func TestLchown(t *testing.T) { testenv.MustHaveSymlink(t) t.Parallel() - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestLchown", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) dir, err := f.Stat() if err != nil { t.Fatalf("stat %s: %s", f.Name(), err) @@ -223,8 +205,7 @@ func TestReaddirRemoveRace(t *testing.T) { } return oldStat(name) } - dir := newDir("TestReaddirRemoveRace", t) - defer RemoveAll(dir) + dir := t.TempDir() if err := WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil { t.Fatal(err) } @@ -255,8 +236,7 @@ func TestMkdirStickyUmask(t *testing.T) { t.Parallel() const umask = 0077 - dir := newDir("TestMkdirStickyUmask", t) - defer RemoveAll(dir) + dir := t.TempDir() oldUmask := syscall.Umask(umask) defer syscall.Umask(oldUmask) From d73a8a206a7d3c179cdc498a29be215fa48a1ec2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 30 May 2024 22:29:35 -0700 Subject: [PATCH 11/72] cmd/cgo: fail on v, err := C.fn when fn is a builtin function We were already checking for _CMalloc, but in fact none of the builtin functions support returning an error. Fixes #67707 Change-Id: I0ee432a9f13ace472c3f36f641efc7d18eda0631 Reviewed-on: https://go-review.googlesource.com/c/go/+/589575 Auto-Submit: Ian Lance Taylor Reviewed-by: Damien Neil Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/cmd/cgo/gcc.go | 4 ++-- src/cmd/cgo/internal/testerrors/errors_test.go | 1 + .../internal/testerrors/testdata/issue67707.go | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/cmd/cgo/internal/testerrors/testdata/issue67707.go diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index b596477b0a..6c23e59adf 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -1601,8 +1601,8 @@ func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr { break } if r.Context == ctxCall2 { - if r.Name.Go == "_CMalloc" { - error_(r.Pos(), "no two-result form for C.malloc") + if builtinDefs[r.Name.Go] != "" { + error_(r.Pos(), "no two-result form for C.%s", r.Name.Go) break } // Invent new Name for the two-result function. diff --git a/src/cmd/cgo/internal/testerrors/errors_test.go b/src/cmd/cgo/internal/testerrors/errors_test.go index 07556007a8..eddfb6583b 100644 --- a/src/cmd/cgo/internal/testerrors/errors_test.go +++ b/src/cmd/cgo/internal/testerrors/errors_test.go @@ -127,6 +127,7 @@ func TestReportsTypeErrors(t *testing.T) { "issue33061.go", "issue50710.go", "issue67517.go", + "issue67707.go", } { check(t, file) } diff --git a/src/cmd/cgo/internal/testerrors/testdata/issue67707.go b/src/cmd/cgo/internal/testerrors/testdata/issue67707.go new file mode 100644 index 0000000000..4f80de165e --- /dev/null +++ b/src/cmd/cgo/internal/testerrors/testdata/issue67707.go @@ -0,0 +1,15 @@ +// Copyright 2024 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 p + +import "C" + +func F() *C.char { + s, err := C.CString("hi") // ERROR HERE: no two-result form + if err != nil { + println(err) + } + return s +} From fed2c11d67dbe6d8179cd411b4bb7761d034e9d2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 18 Jun 2024 17:49:10 -0700 Subject: [PATCH 12/72] iter: minor doc comment updates Remove old return value. Use single variable range for iter.Seq[V]. Rewrite Pairs implementation to not loop forever. Fixes #68056 Fixes #68073 Change-Id: I7ede0fe8ed058bbd57869d87e17b7f2c3641f7dd Reviewed-on: https://go-review.googlesource.com/c/go/+/593555 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil Auto-Submit: Ian Lance Taylor Commit-Queue: Ian Lance Taylor Reviewed-by: Mauri de Souza Meneguzzo --- src/iter/iter.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/iter/iter.go b/src/iter/iter.go index 4ea919b072..14fd8f8115 100644 --- a/src/iter/iter.go +++ b/src/iter/iter.go @@ -31,7 +31,7 @@ element in the sequence, false if it should stop. Iterator functions are most often called by a range loop, as in: func PrintAll[V any](seq iter.Seq[V]) { - for _, v := range seq { + for v := range seq { fmt.Println(v) } } @@ -92,9 +92,8 @@ sequence only once. These “single-use iterators” typically report values from a data stream that cannot be rewound to start over. Calling the iterator again after stopping early may continue the stream, but calling it again after the sequence is finished will yield -no values at all, immediately returning true. Doc comments for -functions or methods that return single-use iterators should document -this fact: +no values at all. Doc comments for functions or methods that return +single-use iterators should document this fact: // Lines returns an iterator over lines read from r. // It returns a single-use iterator. @@ -119,17 +118,24 @@ For example: // Pairs returns an iterator over successive pairs of values from seq. func Pairs[V any](seq iter.Seq[V]) iter.Seq2[V, V] { - return func(yield func(V, V) bool) bool { + return func(yield func(V, V) bool) { next, stop := iter.Pull(seq) defer stop() - v1, ok1 := next() - v2, ok2 := next() - for ok1 || ok2 { + for { + v1, ok1 := next() + if !ok1 { + return + } + v2, ok2 := next() + // If ok2 is false, v2 should be the + // zero value; yield one last pair. if !yield(v1, v2) { - return false + return + } + if !ok2 { + return } } - return true } } From 52ce25b44e8c21f62e95b12497db3036c5bd27c3 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 21 Jun 2024 14:49:21 -0400 Subject: [PATCH 13/72] cmd/vendor: pull in golang.org/x/telemetry@b4de734 Commands run: go get golang.org/x/telemetry@b4de734 go mod tidy go mod vendor For #68109 Change-Id: Ied81cbb111ed66f9bbc94f0db09b5f2430fbff6f Reviewed-on: https://go-review.googlesource.com/c/go/+/594015 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 ++-- .../golang.org/x/telemetry/counter/counter.go | 18 +++++++++++++++++- src/cmd/vendor/modules.txt | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 559ffd1ccd..0625195931 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -9,7 +9,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb + golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 8f9517bc62..25276c92b2 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,8 +16,8 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb h1:0Ge50tvTqbHEyuQDgCYypgL2afqNjRNdl4GHPJuN9QY= -golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 h1:2+8QyQRLYDeEKd+CM/BsuaBaLdhAsNdasS/SnZfPS9g= +golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go index ba1c68889e..7a7e66b22d 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go +++ b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go @@ -15,6 +15,7 @@ import ( "runtime/debug" "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" ) // Inc increments the counter with the given name. @@ -83,11 +84,26 @@ func NewStack(name string, depth int) *StackCounter { // counter file on disk and starts to mmap telemetry counters to the file. // Open also persists any counters already created in the current process. // -// Programs using telemetry should call Open exactly once. +// Programs using telemetry should call either Open or OpenDir exactly once. func Open() { counter.Open() } +// OpenDir prepares telemetry counters for recording to the file system, using +// the specified telemetry directory, if it is not the empty string. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +// +// Programs using telemetry should call either Open or OpenDir exactly once. +func OpenDir(telemetryDir string) { + if telemetryDir != "" { + telemetry.Default = telemetry.NewDir(telemetryDir) + } + counter.Open() +} + // CountFlags creates a counter for every flag that is set // and increments the counter. The name of the counter is // the concatenation of prefix and the flag name. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 8ba7df290f..fc1f25588a 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -45,7 +45,7 @@ golang.org/x/sync/semaphore golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb +# golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter From d79c350916c637de911d93af689a5e4e7ab5a5bb Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 21 Jun 2024 14:35:14 -0400 Subject: [PATCH 14/72] cmd/internal: separate counter package from telemetry package Move the code that opens and increments counters out of the cmd/internal/telemetry package into cmd/internal/telemetry/counter. The telemetry package has dependencies on the upload code, which we do not want to pull into the rest of the go toolchain. For #68109 Change-Id: I463c106819b169177a783de4a7d93377e81f4e3e Reviewed-on: https://go-review.googlesource.com/c/go/+/593976 LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Findley --- src/cmd/addr2line/main.go | 8 +-- src/cmd/asm/main.go | 8 +-- src/cmd/buildid/buildid.go | 8 +-- src/cmd/cgo/main.go | 8 +-- src/cmd/compile/internal/base/flag.go | 4 +- src/cmd/compile/internal/base/print.go | 4 +- src/cmd/compile/internal/gc/main.go | 6 +- src/cmd/covdata/covdata.go | 8 +-- src/cmd/cover/cover.go | 8 +-- src/cmd/dist/buildtool.go | 1 + src/cmd/distpack/pack.go | 8 +-- src/cmd/doc/main.go | 8 +-- src/cmd/fix/main.go | 8 +-- src/cmd/go/internal/help/help.go | 4 +- src/cmd/go/internal/modfetch/cache.go | 4 +- .../internal/telemetrystats/telemetrystats.go | 28 ++++----- .../internal/telemetrystats/version_other.go | 4 +- .../internal/telemetrystats/version_unix.go | 10 +-- .../telemetrystats/version_windows.go | 8 +-- src/cmd/go/internal/tool/tool.go | 10 +-- src/cmd/go/internal/toolchain/select.go | 6 +- src/cmd/go/internal/toolchain/switch.go | 4 +- src/cmd/go/internal/work/buildid.go | 8 +-- src/cmd/go/main.go | 37 +++++------ src/cmd/gofmt/gofmt.go | 8 +-- src/cmd/internal/telemetry/counter/counter.go | 62 +++++++++++++++++++ .../telemetry/counter/counter_bootstrap.go | 20 ++++++ src/cmd/internal/telemetry/telemetry.go | 52 +--------------- .../internal/telemetry/telemetry_bootstrap.go | 22 ++----- src/cmd/link/internal/ld/main.go | 8 +-- src/cmd/nm/nm.go | 8 +-- src/cmd/objdump/main.go | 8 +-- src/cmd/pack/pack.go | 8 +-- src/cmd/pprof/pprof.go | 8 +-- src/cmd/preprofile/main.go | 8 +-- src/cmd/test2json/main.go | 8 +-- src/cmd/trace/main.go | 8 +-- src/cmd/vet/main.go | 8 +-- 38 files changed, 236 insertions(+), 210 deletions(-) create mode 100644 src/cmd/internal/telemetry/counter/counter.go create mode 100644 src/cmd/internal/telemetry/counter/counter_bootstrap.go diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go index b1ec4e0278..500da717ff 100644 --- a/src/cmd/addr2line/main.go +++ b/src/cmd/addr2line/main.go @@ -28,7 +28,7 @@ import ( "strings" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func printUsage(w *os.File) { @@ -46,7 +46,7 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("addr2line: ") - telemetry.OpenCounters() + counter.Open() // pprof expects this behavior when checking for addr2line if len(os.Args) > 1 && os.Args[1] == "--help" { @@ -56,8 +56,8 @@ func main() { flag.Usage = usage flag.Parse() - telemetry.Inc("addr2line/invocations") - telemetry.CountFlags("addr2line/flag:", *flag.CommandLine) + counter.Inc("addr2line/invocations") + counter.CountFlags("addr2line/flag:", *flag.CommandLine) if flag.NArg() != 1 { usage() } diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index ca4e25d047..9fdb7c49a2 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -20,20 +20,20 @@ import ( "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func main() { log.SetFlags(0) log.SetPrefix("asm: ") - telemetry.OpenCounters() + counter.Open() buildcfg.Check() GOARCH := buildcfg.GOARCH flags.Parse() - telemetry.Inc("asm/invocations") - telemetry.CountFlags("asm/flag:", *flag.CommandLine) + counter.Inc("asm/invocations") + counter.CountFlags("asm/flag:", *flag.CommandLine) architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink) if architecture == nil { diff --git a/src/cmd/buildid/buildid.go b/src/cmd/buildid/buildid.go index a008122a0a..a16b96f677 100644 --- a/src/cmd/buildid/buildid.go +++ b/src/cmd/buildid/buildid.go @@ -12,7 +12,7 @@ import ( "strings" "cmd/internal/buildid" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func usage() { @@ -26,11 +26,11 @@ var wflag = flag.Bool("w", false, "write build ID") func main() { log.SetPrefix("buildid: ") log.SetFlags(0) - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("buildid/invocations") - telemetry.CountFlags("buildid/flag:", *flag.CommandLine) + counter.Inc("buildid/invocations") + counter.CountFlags("buildid/flag:", *flag.CommandLine) if flag.NArg() != 1 { usage() } diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index bf879be814..156038b33b 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -28,7 +28,7 @@ import ( "cmd/internal/edit" "cmd/internal/notsha256" "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // A Package collects information about the package we're going to write. @@ -258,11 +258,11 @@ var goarch, goos, gomips, gomips64 string var gccBaseCmd []string func main() { - telemetry.OpenCounters() + counter.Open() objabi.AddVersionFlag() // -V objabi.Flagparse(usage) - telemetry.Inc("cgo/invocations") - telemetry.CountFlags("cgo/flag:", *flag.CommandLine) + counter.Inc("cgo/invocations") + counter.CountFlags("cgo/flag:", *flag.CommandLine) if *gccgoDefineCgoIncomplete { if !*gccgo { diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 8c17c5f27d..b296f3666c 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -6,7 +6,7 @@ package base import ( "cmd/internal/cov/covcmd" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "encoding/json" "flag" "fmt" @@ -195,7 +195,7 @@ func ParseFlags() { objabi.AddVersionFlag() // -V registerFlags() objabi.Flagparse(usage) - telemetry.CountFlags("compile/flag:", *flag.CommandLine) + counter.CountFlags("compile/flag:", *flag.CommandLine) if gcd := os.Getenv("GOCOMPILEDEBUG"); gcd != "" { // This will only override the flags set in gcd; diff --git a/src/cmd/compile/internal/base/print.go b/src/cmd/compile/internal/base/print.go index 15256186af..119f06fbc0 100644 --- a/src/cmd/compile/internal/base/print.go +++ b/src/cmd/compile/internal/base/print.go @@ -14,7 +14,7 @@ import ( "strings" "cmd/internal/src" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // An errorMsg is a queued error message, waiting to be printed. @@ -195,7 +195,7 @@ func Fatalf(format string, args ...interface{}) { FatalfAt(Pos, format, args...) } -var bugStack = telemetry.NewStackCounter("compile/bug", 16) // 16 is arbitrary; used by gopls and crashmonitor +var bugStack = counter.NewStack("compile/bug", 16) // 16 is arbitrary; used by gopls and crashmonitor // FatalfAt reports a fatal error - an internal problem - at pos and exits. // If other errors have already been printed, then FatalfAt just quietly exits. diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 3887d4156d..f68cf4deaf 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -30,7 +30,7 @@ import ( "cmd/internal/obj" "cmd/internal/objabi" "cmd/internal/src" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "internal/buildcfg" @@ -59,8 +59,8 @@ func handlePanic() { // code, and finally writes the compiled package definition to disk. func Main(archInit func(*ssagen.ArchInfo)) { base.Timer.Start("fe", "init") - telemetry.OpenCounters() - telemetry.Inc("compile/invocations") + counter.Open() + counter.Inc("compile/invocations") defer handlePanic() diff --git a/src/cmd/covdata/covdata.go b/src/cmd/covdata/covdata.go index 48d7b9ed08..122ad28b5c 100644 --- a/src/cmd/covdata/covdata.go +++ b/src/cmd/covdata/covdata.go @@ -7,7 +7,7 @@ package main import ( "cmd/internal/cov" "cmd/internal/pkgpattern" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "os" @@ -109,7 +109,7 @@ const ( ) func main() { - telemetry.OpenCounters() + counter.Open() // First argument should be mode/subcommand. if len(os.Args) < 2 { @@ -146,8 +146,8 @@ func main() { op.Usage("") } flag.Parse() - telemetry.Inc("covdata/invocations") - telemetry.CountFlags("covdata/flag:", *flag.CommandLine) + counter.Inc("covdata/invocations") + counter.CountFlags("covdata/flag:", *flag.CommandLine) // Mode-independent flag setup dbgtrace(1, "starting mode-independent setup") diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 47eebaadd3..d8bb989bcc 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -26,7 +26,7 @@ import ( "cmd/internal/edit" "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) const usageMessage = "" + @@ -87,13 +87,13 @@ const ( ) func main() { - telemetry.OpenCounters() + counter.Open() objabi.AddVersionFlag() flag.Usage = usage objabi.Flagparse(usage) - telemetry.Inc("cover/invocations") - telemetry.CountFlags("cover/flag:", *flag.CommandLine) + counter.Inc("cover/invocations") + counter.CountFlags("cover/flag:", *flag.CommandLine) // Usage information when no arguments. if flag.NFlag() == 0 && flag.NArg() == 0 { diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 62f9693210..9ca8fc539c 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -53,6 +53,7 @@ var bootstrapDirs = []string{ "cmd/internal/src", "cmd/internal/sys", "cmd/internal/telemetry", + "cmd/internal/telemetry/counter", "cmd/link", "cmd/link/internal/...", "compress/flate", diff --git a/src/cmd/distpack/pack.go b/src/cmd/distpack/pack.go index 9ad33ee589..5525249366 100644 --- a/src/cmd/distpack/pack.go +++ b/src/cmd/distpack/pack.go @@ -45,7 +45,7 @@ import ( "strings" "time" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func usage() { @@ -69,11 +69,11 @@ var ( func main() { log.SetPrefix("distpack: ") log.SetFlags(0) - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("distpack/invocations") - telemetry.CountFlags("distpack/flag:", *flag.CommandLine) + counter.Inc("distpack/invocations") + counter.CountFlags("distpack/flag:", *flag.CommandLine) if flag.NArg() != 0 { usage() } diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go index 4dbddcb79f..502de097f5 100644 --- a/src/cmd/doc/main.go +++ b/src/cmd/doc/main.go @@ -55,7 +55,7 @@ import ( "path/filepath" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) var ( @@ -87,7 +87,7 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("doc: ") - telemetry.OpenCounters() + counter.Open() dirsInit() err := do(os.Stdout, flag.CommandLine, os.Args[1:]) if err != nil { @@ -108,8 +108,8 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) { flagSet.BoolVar(&showSrc, "src", false, "show source code for symbol") flagSet.BoolVar(&short, "short", false, "one-line representation for each symbol") flagSet.Parse(args) - telemetry.Inc("doc/invocations") - telemetry.CountFlags("doc/flag:", *flag.CommandLine) + counter.Inc("doc/invocations") + counter.CountFlags("doc/flag:", *flag.CommandLine) if chdir != "" { if err := os.Chdir(chdir); err != nil { return err diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index d915ece4ce..6f1ff120da 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -22,7 +22,7 @@ import ( "sort" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) var ( @@ -65,11 +65,11 @@ func usage() { } func main() { - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("fix/invocations") - telemetry.CountFlags("fix/flag:", *flag.CommandLine) + counter.Inc("fix/invocations") + counter.CountFlags("fix/flag:", *flag.CommandLine) if !version.IsValid(*goVersion) { report(fmt.Errorf("invalid -go=%s", *goVersion)) diff --git a/src/cmd/go/internal/help/help.go b/src/cmd/go/internal/help/help.go index 98382f2423..4f2607fef2 100644 --- a/src/cmd/go/internal/help/help.go +++ b/src/cmd/go/internal/help/help.go @@ -16,10 +16,10 @@ import ( "unicode/utf8" "cmd/go/internal/base" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) -var counterErrorsHelpUnknownTopic = telemetry.NewCounter("go/errors:help-unknown-topic") +var counterErrorsHelpUnknownTopic = counter.New("go/errors:help-unknown-topic") // Help implements the 'help' command. func Help(w io.Writer, args []string) { diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index 75b28b9bbc..02c4833a1b 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -26,7 +26,7 @@ import ( "cmd/go/internal/modfetch/codehost" "cmd/go/internal/par" "cmd/go/internal/robustio" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/mod/module" "golang.org/x/mod/semver" @@ -779,7 +779,7 @@ var ( statCacheOnce sync.Once statCacheErr error - counterErrorsGOMODCACHEEntryRelative = telemetry.NewCounter("go/errors:gomodcache-entry-relative") + counterErrorsGOMODCACHEEntryRelative = counter.New("go/errors:gomodcache-entry-relative") ) // checkCacheDir checks if the directory specified by GOMODCACHE exists. An diff --git a/src/cmd/go/internal/telemetrystats/telemetrystats.go b/src/cmd/go/internal/telemetrystats/telemetrystats.go index 610c4a22e8..950453fa95 100644 --- a/src/cmd/go/internal/telemetrystats/telemetrystats.go +++ b/src/cmd/go/internal/telemetrystats/telemetrystats.go @@ -10,7 +10,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/modload" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func Increment() { @@ -22,30 +22,30 @@ func Increment() { // the command is running in. func incrementConfig() { if !modload.WillBeEnabled() { - telemetry.Inc("go/mode:gopath") + counter.Inc("go/mode:gopath") } else if workfile := modload.FindGoWork(base.Cwd()); workfile != "" { - telemetry.Inc("go/mode:workspace") + counter.Inc("go/mode:workspace") } else { - telemetry.Inc("go/mode:module") + counter.Inc("go/mode:module") } - telemetry.Inc("go/platform/target/goos:" + cfg.Goos) - telemetry.Inc("go/platform/target/goarch:" + cfg.Goarch) + counter.Inc("go/platform/target/goos:" + cfg.Goos) + counter.Inc("go/platform/target/goarch:" + cfg.Goarch) switch cfg.Goarch { case "386": - telemetry.Inc("go/platform/target/go386:" + cfg.GO386) + counter.Inc("go/platform/target/go386:" + cfg.GO386) case "amd64": - telemetry.Inc("go/platform/target/goamd64:" + cfg.GOAMD64) + counter.Inc("go/platform/target/goamd64:" + cfg.GOAMD64) case "arm": - telemetry.Inc("go/platform/target/goarm:" + cfg.GOARM) + counter.Inc("go/platform/target/goarm:" + cfg.GOARM) case "arm64": - telemetry.Inc("go/platform/target/goarm64:" + cfg.GOARM64) + counter.Inc("go/platform/target/goarm64:" + cfg.GOARM64) case "mips": - telemetry.Inc("go/platform/target/gomips:" + cfg.GOMIPS) + counter.Inc("go/platform/target/gomips:" + cfg.GOMIPS) case "ppc64": - telemetry.Inc("go/platform/target/goppc64:" + cfg.GOPPC64) + counter.Inc("go/platform/target/goppc64:" + cfg.GOPPC64) case "riscv64": - telemetry.Inc("go/platform/target/goriscv64:" + cfg.GORISCV64) + counter.Inc("go/platform/target/goriscv64:" + cfg.GORISCV64) case "wasm": - telemetry.Inc("go/platform/target/gowasm:" + cfg.GOWASM) + counter.Inc("go/platform/target/gowasm:" + cfg.GOWASM) } } diff --git a/src/cmd/go/internal/telemetrystats/version_other.go b/src/cmd/go/internal/telemetrystats/version_other.go index b20294e223..efce5fcf36 100644 --- a/src/cmd/go/internal/telemetrystats/version_other.go +++ b/src/cmd/go/internal/telemetrystats/version_other.go @@ -6,8 +6,8 @@ package telemetrystats -import "cmd/internal/telemetry" +import "cmd/internal/telemetry/counter" func incrementVersionCounters() { - telemetry.Inc("go/platform:version-not-supported") + counter.Inc("go/platform:version-not-supported") } diff --git a/src/cmd/go/internal/telemetrystats/version_unix.go b/src/cmd/go/internal/telemetrystats/version_unix.go index 08259b7c89..517e7829b6 100644 --- a/src/cmd/go/internal/telemetrystats/version_unix.go +++ b/src/cmd/go/internal/telemetrystats/version_unix.go @@ -12,7 +12,7 @@ import ( "runtime" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/sys/unix" ) @@ -29,7 +29,7 @@ func incrementVersionCounters() { var v unix.Utsname err := unix.Uname(&v) if err != nil { - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-uname-error", runtime.GOOS)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-uname-error", runtime.GOOS)) return } major, minor, ok := majorMinor(convert(v.Release[:])) @@ -37,11 +37,11 @@ func incrementVersionCounters() { major, minor, ok = convert(v.Version[:]), convert(v.Release[:]), true } if !ok { - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-bad-format", runtime.GOOS)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-bad-format", runtime.GOOS)) return } - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/major-version:%s", runtime.GOOS, major)) - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/version:%s-%s", runtime.GOOS, major, minor)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/major-version:%s", runtime.GOOS, major)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/version:%s-%s", runtime.GOOS, major, minor)) } func majorMinor(v string) (string, string, bool) { diff --git a/src/cmd/go/internal/telemetrystats/version_windows.go b/src/cmd/go/internal/telemetrystats/version_windows.go index e6a33e00cd..7de87193c6 100644 --- a/src/cmd/go/internal/telemetrystats/version_windows.go +++ b/src/cmd/go/internal/telemetrystats/version_windows.go @@ -9,14 +9,14 @@ package telemetrystats import ( "fmt" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/sys/windows" ) func incrementVersionCounters() { v := windows.RtlGetVersion() - telemetry.Inc(fmt.Sprintf("go/platform/host/windows/major-version:%d", v.MajorVersion)) - telemetry.Inc(fmt.Sprintf("go/platform/host/windows/version:%d-%d", v.MajorVersion, v.MinorVersion)) - telemetry.Inc(fmt.Sprintf("go/platform/host/windows/build:%d", v.BuildNumber)) + counter.Inc(fmt.Sprintf("go/platform/host/windows/major-version:%d", v.MajorVersion)) + counter.Inc(fmt.Sprintf("go/platform/host/windows/version:%d-%d", v.MajorVersion, v.MinorVersion)) + counter.Inc(fmt.Sprintf("go/platform/host/windows/build:%d", v.BuildNumber)) } diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go index da219f041c..77cee564b3 100644 --- a/src/cmd/go/internal/tool/tool.go +++ b/src/cmd/go/internal/tool/tool.go @@ -6,7 +6,7 @@ package tool import ( - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "context" "encoding/json" "flag" @@ -58,7 +58,7 @@ func init() { func runTool(ctx context.Context, cmd *base.Command, args []string) { if len(args) == 0 { - telemetry.Inc("go/subcommand:tool") + counter.Inc("go/subcommand:tool") listTools() return } @@ -86,17 +86,17 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) { if impersonateDistList(args[2:]) { // If it becomes necessary, we could increment an additional counter to indicate // that we're impersonating dist list if knowing that becomes important? - telemetry.Inc("go/subcommand:tool-dist") + counter.Inc("go/subcommand:tool-dist") return } } - telemetry.Inc("go/subcommand:tool-unknown") + counter.Inc("go/subcommand:tool-unknown") // Emit the usual error for the missing tool. _ = base.Tool(toolName) } else { // Increment a counter for the tool subcommand with the tool name. - telemetry.Inc("go/subcommand:tool-" + toolName) + counter.Inc("go/subcommand:tool-" + toolName) } if toolN { diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go index d4787a844f..8e93e6c903 100644 --- a/src/cmd/go/internal/toolchain/select.go +++ b/src/cmd/go/internal/toolchain/select.go @@ -26,7 +26,7 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/run" "cmd/go/internal/work" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/mod/module" ) @@ -82,7 +82,7 @@ func FilterEnv(env []string) []string { return out } -var counterErrorsInvalidToolchainInFile = telemetry.NewCounter("go/errors:invalid-toolchain-in-file") +var counterErrorsInvalidToolchainInFile = counter.New("go/errors:invalid-toolchain-in-file") // Select invokes a different Go toolchain if directed by // the GOTOOLCHAIN environment variable or the user's configuration @@ -253,7 +253,7 @@ func Select() { Exec(gotoolchain) } -var counterSelectExec = telemetry.NewCounter("go/toolchain/select-exec") +var counterSelectExec = counter.New("go/toolchain/select-exec") // TestVersionSwitch is set in the test go binary to the value in $TESTGO_VERSION_SWITCH. // Valid settings are: diff --git a/src/cmd/go/internal/toolchain/switch.go b/src/cmd/go/internal/toolchain/switch.go index ba1e6973cf..37c1bcdcbe 100644 --- a/src/cmd/go/internal/toolchain/switch.go +++ b/src/cmd/go/internal/toolchain/switch.go @@ -16,7 +16,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/gover" "cmd/go/internal/modfetch" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // A Switcher collects errors to be reported and then decides @@ -104,7 +104,7 @@ func (s *Switcher) Switch(ctx context.Context) { panic("unreachable") } -var counterSwitchExec = telemetry.NewCounter("go/toolchain/switch-exec") +var counterSwitchExec = counter.New("go/toolchain/switch-exec") // SwitchOrFatal attempts a toolchain switch based on the information in err // and otherwise falls back to base.Fatal(err). diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 889cc6ca50..4ee43e2436 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -19,7 +19,7 @@ import ( "cmd/go/internal/str" "cmd/internal/buildid" "cmd/internal/quoted" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // Build IDs @@ -406,11 +406,11 @@ func (b *Builder) fileHash(file string) string { } var ( - counterCacheHit = telemetry.NewCounter("go/buildcache/hit") - counterCacheMiss = telemetry.NewCounter("go/buildcache/miss") + counterCacheHit = counter.New("go/buildcache/hit") + counterCacheMiss = counter.New("go/buildcache/miss") onceIncStdlibRecompiled sync.Once - stdlibRecompiled = telemetry.NewCounter("go/buildcache/stdlib-recompiled") + stdlibRecompiled = counter.New("go/buildcache/stdlib-recompiled") ) // useCache tries to satisfy the action a, which has action ID actionHash, diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index eb33df1ad4..1c58232a66 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -45,6 +45,7 @@ import ( "cmd/go/internal/work" "cmd/go/internal/workcmd" "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func init() { @@ -91,20 +92,20 @@ func init() { var _ = go11tag -var counterErrorsGOPATHEntryRelative = telemetry.NewCounter("go/errors:gopath-entry-relative") +var counterErrorsGOPATHEntryRelative = counter.New("go/errors:gopath-entry-relative") func main() { log.SetFlags(0) - telemetry.MaybeChild() // Run in child mode if this is the telemetry sidecar child process. - telemetry.OpenCounters() // Open the telemetry counter file so counters can be written to it. + telemetry.MaybeChild() // Run in child mode if this is the telemetry sidecar child process. + counter.Open() // Open the telemetry counter file so counters can be written to it. handleChdirFlag() toolchain.Select() telemetry.MaybeParent() // Run the upload process. Opening the counter file is idempotent. flag.Usage = base.Usage flag.Parse() - telemetry.Inc("go/invocations") - telemetry.CountFlags("go/flag:", *flag.CommandLine) + counter.Inc("go/invocations") + counter.CountFlags("go/flag:", *flag.CommandLine) args := flag.Args() if len(args) < 1 { @@ -113,7 +114,7 @@ func main() { cfg.CmdName = args[0] // for error messages if args[0] == "help" { - telemetry.Inc("go/subcommand:" + strings.Join(append([]string{"help"}, args[1:]...), "-")) + counter.Inc("go/subcommand:" + strings.Join(append([]string{"help"}, args[1:]...), "-")) help.Help(os.Stdout, args[1:]) return } @@ -128,17 +129,17 @@ func main() { } switch strings.ToLower(cfg.GOROOT) { case "/usr/local/go": // Location recommended for installation on Linux and Darwin and used by Mac installer. - telemetry.Inc("go/goroot:usr-local-go") + counter.Inc("go/goroot:usr-local-go") case "/usr/lib/go": // A typical location used by Linux package managers. - telemetry.Inc("go/goroot:usr-lib-go") + counter.Inc("go/goroot:usr-lib-go") case "/usr/lib/golang": // Another typical location used by Linux package managers. - telemetry.Inc("go/goroot:usr-lib-golang") + counter.Inc("go/goroot:usr-lib-golang") case `c:\program files\go`: // Location used by Windows installer. - telemetry.Inc("go/goroot:program-files-go") + counter.Inc("go/goroot:program-files-go") case `c:\program files (x86)\go`: // Location used by 386 Windows installer on amd64 platform. - telemetry.Inc("go/goroot:program-files-x86-go") + counter.Inc("go/goroot:program-files-x86-go") default: - telemetry.Inc("go/goroot:other") + counter.Inc("go/goroot:other") } // Diagnose common mistake: GOPATH==GOROOT. @@ -184,7 +185,7 @@ func main() { } if args[used] == "help" { // Accept 'go mod help' and 'go mod help foo' for 'go help mod' and 'go help mod foo'. - telemetry.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-") + "-" + strings.Join(args[used:], "-")) + counter.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-") + "-" + strings.Join(args[used:], "-")) help.Help(os.Stdout, append(slices.Clip(args[:used]), args[used+1:]...)) base.Exit() } @@ -196,7 +197,7 @@ func main() { if cmdName == "" { cmdName = args[0] } - telemetry.Inc("go/subcommand:unknown") + counter.Inc("go/subcommand:unknown") fmt.Fprintf(os.Stderr, "go %s: unknown command\nRun 'go help%s' for usage.\n", cmdName, helpArg) base.SetExitStatus(2) base.Exit() @@ -206,7 +207,7 @@ func main() { // increment in the tool subcommand's Run function because we need // to do the flag processing in invoke first. if cfg.CmdName != "tool" { - telemetry.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-")) + counter.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-")) } telemetrystats.Increment() invoke(cmd, args[used-1:]) @@ -274,8 +275,8 @@ func invoke(cmd *base.Command, args []string) { base.SetFromGOFLAGS(&cmd.Flag) cmd.Flag.Parse(args[1:]) flagCounterPrefix := "go/" + strings.ReplaceAll(cfg.CmdName, " ", "-") + "/flag" - telemetry.CountFlags(flagCounterPrefix+":", cmd.Flag) - telemetry.CountFlagValue(flagCounterPrefix+"/", cmd.Flag, "buildmode") + counter.CountFlags(flagCounterPrefix+":", cmd.Flag) + counter.CountFlagValue(flagCounterPrefix+"/", cmd.Flag, "buildmode") args = cmd.Flag.Args() } @@ -361,7 +362,7 @@ func handleChdirFlag() { _, dir, _ = strings.Cut(a, "=") os.Args = slices.Delete(os.Args, used, used+1) } - telemetry.Inc("go/flag:C") + counter.Inc("go/flag:C") if err := os.Chdir(dir); err != nil { base.Fatalf("go: %v", err) diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index d6721f9327..d91a75b105 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -25,7 +25,7 @@ import ( "strconv" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/sync/semaphore" ) @@ -374,11 +374,11 @@ func main() { } func gofmtMain(s *sequencer) { - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("gofmt/invocations") - telemetry.CountFlags("gofmt/flag:", *flag.CommandLine) + counter.Inc("gofmt/invocations") + counter.CountFlags("gofmt/flag:", *flag.CommandLine) if *cpuprofile != "" { fdSem <- true diff --git a/src/cmd/internal/telemetry/counter/counter.go b/src/cmd/internal/telemetry/counter/counter.go new file mode 100644 index 0000000000..5cef0b0041 --- /dev/null +++ b/src/cmd/internal/telemetry/counter/counter.go @@ -0,0 +1,62 @@ +// Copyright 2024 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. + +//go:build !cmd_go_bootstrap && !compiler_bootstrap + +package counter + +import ( + "flag" + "os" + + "golang.org/x/telemetry/counter" +) + +var openCalled bool + +func OpenCalled() bool { return openCalled } + +// Open opens the counter files for writing if telemetry is supported +// on the current platform (and does nothing otherwise). +func Open() { + openCalled = true + counter.OpenDir(os.Getenv("TEST_TELEMETRY_DIR")) +} + +// Inc increments the counter with the given name. +func Inc(name string) { + counter.Inc(name) +} + +// New returns a counter with the given name. +func New(name string) *counter.Counter { + return counter.New(name) +} + +// NewStack returns a new stack counter with the given name and depth. +func NewStack(name string, depth int) *counter.StackCounter { + return counter.NewStack(name, depth) +} + +// CountFlags creates a counter for every flag that is set +// and increments the counter. The name of the counter is +// the concatenation of prefix and the flag name. +func CountFlags(prefix string, flagSet flag.FlagSet) { + counter.CountFlags(prefix, flagSet) +} + +// CountFlagValue creates a counter for the flag value +// if it is set and increments the counter. The name of the +// counter is the concatenation of prefix, the flagName, ":", +// and value.String() for the flag's value. +func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) { + // TODO(matloob): Maybe pass in a list of flagNames if we end up counting + // values for more than one? + // TODO(matloob): Add this to x/telemetry? + flagSet.Visit(func(f *flag.Flag) { + if f.Name == flagName { + counter.New(prefix + f.Name + ":" + f.Value.String()).Inc() + } + }) +} diff --git a/src/cmd/internal/telemetry/counter/counter_bootstrap.go b/src/cmd/internal/telemetry/counter/counter_bootstrap.go new file mode 100644 index 0000000000..0080829405 --- /dev/null +++ b/src/cmd/internal/telemetry/counter/counter_bootstrap.go @@ -0,0 +1,20 @@ +// Copyright 2024 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. + +//go:build cmd_go_bootstrap || compiler_bootstrap + +package counter + +import "flag" + +type dummyCounter struct{} + +func (dc dummyCounter) Inc() {} + +func Open() {} +func Inc(name string) {} +func New(name string) dummyCounter { return dummyCounter{} } +func NewStack(name string, depth int) dummyCounter { return dummyCounter{} } +func CountFlags(name string, flagSet flag.FlagSet) {} +func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) {} diff --git a/src/cmd/internal/telemetry/telemetry.go b/src/cmd/internal/telemetry/telemetry.go index b0c864a1a9..ca84fe39b1 100644 --- a/src/cmd/internal/telemetry/telemetry.go +++ b/src/cmd/internal/telemetry/telemetry.go @@ -12,30 +12,21 @@ package telemetry import ( - "flag" "os" + "cmd/internal/telemetry/counter" + "golang.org/x/telemetry" - "golang.org/x/telemetry/counter" ) var openCountersCalled, maybeChildCalled bool -// OpenCounters opens the counter files for writing if telemetry is supported -// on the current platform (and does nothing otherwise). -func OpenCounters() { - openCountersCalled = true - telemetry.Start(telemetry.Config{ - TelemetryDir: os.Getenv("TEST_TELEMETRY_DIR"), - }) -} - // MaybeParent does a once a day check to see if the weekly reports are // ready to be processed or uploaded, and if so, starts the telemetry child to // do so. It should only be called by cmd/go, and only after OpenCounters and MaybeChild // have already been called. func MaybeParent() { - if !openCountersCalled || !maybeChildCalled { + if !counter.OpenCalled() || !maybeChildCalled { panic("MaybeParent must be called after OpenCounters and MaybeChild") } telemetry.Start(telemetry.Config{ @@ -56,43 +47,6 @@ func MaybeChild() { }) } -// Inc increments the counter with the given name. -func Inc(name string) { - counter.Inc(name) -} - -// NewCounter returns a counter with the given name. -func NewCounter(name string) *counter.Counter { - return counter.New(name) -} - -// NewStackCounter returns a new stack counter with the given name and depth. -func NewStackCounter(name string, depth int) *counter.StackCounter { - return counter.NewStack(name, depth) -} - -// CountFlags creates a counter for every flag that is set -// and increments the counter. The name of the counter is -// the concatenation of prefix and the flag name. -func CountFlags(prefix string, flagSet flag.FlagSet) { - counter.CountFlags(prefix, flagSet) -} - -// CountFlagValue creates a counter for the flag value -// if it is set and increments the counter. The name of the -// counter is the concatenation of prefix, the flagName, ":", -// and value.String() for the flag's value. -func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) { - // TODO(matloob): Maybe pass in a list of flagNames if we end up counting - // values for more than one? - // TODO(matloob): Add this to x/telemetry? - flagSet.Visit(func(f *flag.Flag) { - if f.Name == flagName { - counter.New(prefix + f.Name + ":" + f.Value.String()).Inc() - } - }) -} - // Mode returns the current telemetry mode. // // The telemetry mode is a global value that controls both the local collection diff --git a/src/cmd/internal/telemetry/telemetry_bootstrap.go b/src/cmd/internal/telemetry/telemetry_bootstrap.go index 05c0ee1c56..e301e30cc8 100644 --- a/src/cmd/internal/telemetry/telemetry_bootstrap.go +++ b/src/cmd/internal/telemetry/telemetry_bootstrap.go @@ -6,20 +6,8 @@ package telemetry -import "flag" - -type dummyCounter struct{} - -func (dc dummyCounter) Inc() {} - -func OpenCounters() {} -func MaybeParent() {} -func MaybeChild() {} -func Inc(name string) {} -func NewCounter(name string) dummyCounter { return dummyCounter{} } -func NewStackCounter(name string, depth int) dummyCounter { return dummyCounter{} } -func CountFlags(name string, flagSet flag.FlagSet) {} -func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) {} -func Mode() string { return "" } -func SetMode(mode string) error { return nil } -func Dir() string { return "" } +func MaybeParent() {} +func MaybeChild() {} +func Mode() string { return "" } +func SetMode(mode string) error { return nil } +func Dir() string { return "" } diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 3183e1a13e..56e865d8a5 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -36,7 +36,7 @@ import ( "cmd/internal/objabi" "cmd/internal/quoted" "cmd/internal/sys" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "cmd/link/internal/benchmark" "flag" "internal/buildcfg" @@ -157,8 +157,8 @@ func (t *ternaryFlag) IsBoolFlag() bool { return true } // parse like a boolean func Main(arch *sys.Arch, theArch Arch) { log.SetPrefix("link: ") log.SetFlags(0) - telemetry.OpenCounters() - telemetry.Inc("link/invocations") + counter.Open() + counter.Inc("link/invocations") thearch = theArch ctxt := linknew(arch) @@ -204,7 +204,7 @@ func Main(arch *sys.Arch, theArch Arch) { objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg) objabi.Flagparse(usage) - telemetry.CountFlags("link/flag:", *flag.CommandLine) + counter.CountFlags("link/flag:", *flag.CommandLine) if ctxt.Debugvlog > 0 { // dump symbol info on crash diff --git a/src/cmd/nm/nm.go b/src/cmd/nm/nm.go index e0d98d5f6c..752870654d 100644 --- a/src/cmd/nm/nm.go +++ b/src/cmd/nm/nm.go @@ -13,7 +13,7 @@ import ( "sort" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) const helpText = `usage: go tool nm [options] file... @@ -68,11 +68,11 @@ func (nflag) String() string { func main() { log.SetFlags(0) - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("nm/invocations") - telemetry.CountFlags("nm/flag:", *flag.CommandLine) + counter.Inc("nm/invocations") + counter.CountFlags("nm/flag:", *flag.CommandLine) switch *sortOrder { case "address", "name", "none", "size": diff --git a/src/cmd/objdump/main.go b/src/cmd/objdump/main.go index 7554b5500c..b5b0d7f517 100644 --- a/src/cmd/objdump/main.go +++ b/src/cmd/objdump/main.go @@ -41,7 +41,7 @@ import ( "strings" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) var printCode = flag.Bool("S", false, "print Go code alongside assembly") @@ -58,12 +58,12 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("objdump: ") - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("objdump/invocations") - telemetry.CountFlags("objdump/flag:", *flag.CommandLine) + counter.Inc("objdump/invocations") + counter.CountFlags("objdump/flag:", *flag.CommandLine) if flag.NArg() != 1 && flag.NArg() != 3 { usage() } diff --git a/src/cmd/pack/pack.go b/src/cmd/pack/pack.go index 28f217ace1..4ac6ce995f 100644 --- a/src/cmd/pack/pack.go +++ b/src/cmd/pack/pack.go @@ -6,7 +6,7 @@ package main import ( "cmd/internal/archive" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "fmt" "io" "io/fs" @@ -31,7 +31,7 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("pack: ") - telemetry.OpenCounters() + counter.Open() // need "pack op archive" at least. if len(os.Args) < 3 { log.Print("not enough arguments") @@ -39,8 +39,8 @@ func main() { usage() } setOp(os.Args[1]) - telemetry.Inc("pack/invocations") - telemetry.Inc("pack/op:" + string(op)) + counter.Inc("pack/invocations") + counter.Inc("pack/op:" + string(op)) var ar *Archive switch op { case 'p': diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go index 722b745287..a1c2cd210f 100644 --- a/src/cmd/pprof/pprof.go +++ b/src/cmd/pprof/pprof.go @@ -25,22 +25,22 @@ import ( "time" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "github.com/google/pprof/driver" "github.com/google/pprof/profile" ) func main() { - telemetry.OpenCounters() - telemetry.Inc("pprof/invocations") + counter.Open() + counter.Inc("pprof/invocations") options := &driver.Options{ Fetch: new(fetcher), Obj: new(objTool), UI: newUI(), } err := driver.PProf(options) - telemetry.CountFlags("pprof/flag:", *flag.CommandLine) // pprof will use the flag package as its default + counter.CountFlags("pprof/flag:", *flag.CommandLine) // pprof will use the flag package as its default if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(2) diff --git a/src/cmd/preprofile/main.go b/src/cmd/preprofile/main.go index 1260eed104..60aa1f7cc6 100644 --- a/src/cmd/preprofile/main.go +++ b/src/cmd/preprofile/main.go @@ -18,7 +18,7 @@ import ( "bufio" "cmd/internal/objabi" "cmd/internal/pgo" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "log" @@ -73,12 +73,12 @@ func main() { log.SetFlags(0) log.SetPrefix("preprofile: ") - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("preprofile/invocations") - telemetry.CountFlags("preprofile/flag:", *flag.CommandLine) + counter.Inc("preprofile/invocations") + counter.CountFlags("preprofile/flag:", *flag.CommandLine) if *input == "" { log.Print("Input pprof path required (-i)") usage() diff --git a/src/cmd/test2json/main.go b/src/cmd/test2json/main.go index 844ee5aa6c..b704dd4d31 100644 --- a/src/cmd/test2json/main.go +++ b/src/cmd/test2json/main.go @@ -96,7 +96,7 @@ import ( "os/exec" "os/signal" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "cmd/internal/test2json" ) @@ -116,12 +116,12 @@ func ignoreSignals() { } func main() { - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("test2json/invocations") - telemetry.CountFlags("test2json/flag:", *flag.CommandLine) + counter.Inc("test2json/invocations") + counter.CountFlags("test2json/flag:", *flag.CommandLine) var mode test2json.Mode if *flagT { diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index e48048b9f2..d51ee58164 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -6,7 +6,7 @@ package main import ( "cmd/internal/browser" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "internal/trace" @@ -64,14 +64,14 @@ var ( ) func main() { - telemetry.OpenCounters() + counter.Open() flag.Usage = func() { fmt.Fprint(os.Stderr, usageMessage) os.Exit(2) } flag.Parse() - telemetry.Inc("trace/invocations") - telemetry.CountFlags("trace/flag:", *flag.CommandLine) + counter.Inc("trace/invocations") + counter.CountFlags("trace/flag:", *flag.CommandLine) // Go 1.7 traces embed symbol info and does not require the binary. // But we optionally accept binary as first arg for Go 1.5 traces. diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go index 84821d43fc..3ace8ad689 100644 --- a/src/cmd/vet/main.go +++ b/src/cmd/vet/main.go @@ -6,7 +6,7 @@ package main import ( "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "golang.org/x/tools/go/analysis/unitchecker" @@ -47,10 +47,10 @@ import ( ) func main() { - telemetry.OpenCounters() + counter.Open() objabi.AddVersionFlag() - telemetry.Inc("vet/invocations") + counter.Inc("vet/invocations") unitchecker.Main( appends.Analyzer, asmdecl.Analyzer, @@ -89,5 +89,5 @@ func main() { // It's possible that unitchecker will exit early. In // those cases the flags won't be counted. - telemetry.CountFlags("vet/flag:", *flag.CommandLine) + counter.CountFlags("vet/flag:", *flag.CommandLine) } From cb3b34349b4608a8eb5107159db74cbe472744b2 Mon Sep 17 00:00:00 2001 From: Gopher Robot Date: Fri, 21 Jun 2024 19:19:05 +0000 Subject: [PATCH 15/72] doc/next: delete The release note fragments have been merged and added as _content/doc/go1.23.md in x/website in CL 594035. For #65614. Change-Id: I7c8c718bc065024b6bdca93ce9bcc3c5d8b2dbc7 Reviewed-on: https://go-review.googlesource.com/c/go/+/594036 LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Auto-Submit: Dmitri Shuralyov Reviewed-by: David Chase Reviewed-by: Dmitri Shuralyov --- doc/next/1-intro.md | 14 ---- doc/next/2-language.md | 18 ---- doc/next/3-tools.md | 84 ------------------- doc/next/4-runtime.md | 7 -- doc/next/5-toolchain.md | 38 --------- doc/next/6-stdlib/0-heading.md | 2 - doc/next/6-stdlib/1-time.md | 32 ------- doc/next/6-stdlib/2-unique.md | 13 --- doc/next/6-stdlib/3-iter.md | 29 ------- doc/next/6-stdlib/4-structs.md | 11 --- doc/next/6-stdlib/99-minor/0-heading.md | 3 - doc/next/6-stdlib/99-minor/README | 1 - .../6-stdlib/99-minor/archive/tar/50102.md | 4 - .../6-stdlib/99-minor/crypto/tls/63369.md | 3 - .../6-stdlib/99-minor/crypto/tls/63691.md | 3 - .../6-stdlib/99-minor/crypto/tls/66214.md | 3 - .../6-stdlib/99-minor/crypto/tls/67061.md | 3 - .../6-stdlib/99-minor/crypto/tls/67065.md | 3 - .../6-stdlib/99-minor/crypto/x509/45990.md | 3 - .../6-stdlib/99-minor/crypto/x509/62048.md | 4 - .../6-stdlib/99-minor/crypto/x509/66249.md | 3 - .../6-stdlib/99-minor/database/sql/64707.md | 3 - doc/next/6-stdlib/99-minor/debug/elf/66054.md | 3 - doc/next/6-stdlib/99-minor/debug/elf/66836.md | 2 - .../99-minor/encoding/binary/60023.md | 3 - doc/next/6-stdlib/99-minor/go/ast/66339.md | 2 - doc/next/6-stdlib/99-minor/go/types/46477.md | 1 - doc/next/6-stdlib/99-minor/go/types/65772.md | 3 - doc/next/6-stdlib/99-minor/go/types/66559.md | 3 - doc/next/6-stdlib/99-minor/go/types/67143.md | 2 - .../6-stdlib/99-minor/go/types/cl-577715.md | 4 - doc/next/6-stdlib/99-minor/iter/61897.md | 1 - doc/next/6-stdlib/99-minor/maps/61900.md | 1 - .../6-stdlib/99-minor/math/rand/v2/61716.md | 2 - .../6-stdlib/99-minor/math/rand/v2/67059.md | 1 - doc/next/6-stdlib/99-minor/net/62254.md | 3 - doc/next/6-stdlib/99-minor/net/63116.md | 3 - doc/next/6-stdlib/99-minor/net/67925.md | 3 - doc/next/6-stdlib/99-minor/net/http/46443.md | 3 - doc/next/6-stdlib/99-minor/net/http/61472.md | 1 - doc/next/6-stdlib/99-minor/net/http/62490.md | 1 - doc/next/6-stdlib/99-minor/net/http/64910.md | 2 - doc/next/6-stdlib/99-minor/net/http/66008.md | 7 -- doc/next/6-stdlib/99-minor/net/http/66343.md | 16 ---- doc/next/6-stdlib/99-minor/net/http/66405.md | 3 - .../99-minor/net/http/httptest/59473.md | 2 - doc/next/6-stdlib/99-minor/os/33357.md | 3 - doc/next/6-stdlib/99-minor/os/61893.md | 7 -- doc/next/6-stdlib/99-minor/os/62484.md | 1 - doc/next/6-stdlib/99-minor/os/63703.md | 5 -- .../6-stdlib/99-minor/path/filepath/57151.md | 2 - .../6-stdlib/99-minor/path/filepath/63703.md | 11 --- doc/next/6-stdlib/99-minor/reflect/60427.md | 6 -- doc/next/6-stdlib/99-minor/reflect/61308.md | 3 - doc/next/6-stdlib/99-minor/reflect/66056.md | 4 - .../6-stdlib/99-minor/runtime/debug/42888.md | 5 -- .../6-stdlib/99-minor/runtime/debug/67182.md | 1 - .../6-stdlib/99-minor/runtime/pprof/43669.md | 2 - .../6-stdlib/99-minor/runtime/trace/65319.md | 4 - doc/next/6-stdlib/99-minor/slices/53987.md | 1 - doc/next/6-stdlib/99-minor/slices/61899.md | 1 - doc/next/6-stdlib/99-minor/slices/65238.md | 2 - doc/next/6-stdlib/99-minor/structs/66408.md | 1 - doc/next/6-stdlib/99-minor/sync/61696.md | 2 - .../6-stdlib/99-minor/sync/atomic/61395.md | 3 - doc/next/6-stdlib/99-minor/syscall/62254.md | 1 - doc/next/6-stdlib/99-minor/syscall/65817.md | 1 - .../6-stdlib/99-minor/testing/fstest/63675.md | 3 - .../6-stdlib/99-minor/text/template/57646.md | 1 - doc/next/6-stdlib/99-minor/time/67470.md | 2 - .../6-stdlib/99-minor/unicode/utf16/44940.md | 3 - doc/next/6-stdlib/99-minor/unique/62483.md | 1 - doc/next/7-ports.md | 38 --------- doc/next/9-todo.md | 51 ----------- 74 files changed, 521 deletions(-) delete mode 100644 doc/next/1-intro.md delete mode 100644 doc/next/2-language.md delete mode 100644 doc/next/3-tools.md delete mode 100644 doc/next/4-runtime.md delete mode 100644 doc/next/5-toolchain.md delete mode 100644 doc/next/6-stdlib/0-heading.md delete mode 100644 doc/next/6-stdlib/1-time.md delete mode 100644 doc/next/6-stdlib/2-unique.md delete mode 100644 doc/next/6-stdlib/3-iter.md delete mode 100644 doc/next/6-stdlib/4-structs.md delete mode 100644 doc/next/6-stdlib/99-minor/0-heading.md delete mode 100644 doc/next/6-stdlib/99-minor/README delete mode 100644 doc/next/6-stdlib/99-minor/archive/tar/50102.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/63369.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/63691.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/66214.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/67061.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/67065.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/45990.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/62048.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/66249.md delete mode 100644 doc/next/6-stdlib/99-minor/database/sql/64707.md delete mode 100644 doc/next/6-stdlib/99-minor/debug/elf/66054.md delete mode 100644 doc/next/6-stdlib/99-minor/debug/elf/66836.md delete mode 100644 doc/next/6-stdlib/99-minor/encoding/binary/60023.md delete mode 100644 doc/next/6-stdlib/99-minor/go/ast/66339.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/46477.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/65772.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/66559.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/67143.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/cl-577715.md delete mode 100644 doc/next/6-stdlib/99-minor/iter/61897.md delete mode 100644 doc/next/6-stdlib/99-minor/maps/61900.md delete mode 100644 doc/next/6-stdlib/99-minor/math/rand/v2/61716.md delete mode 100644 doc/next/6-stdlib/99-minor/math/rand/v2/67059.md delete mode 100644 doc/next/6-stdlib/99-minor/net/62254.md delete mode 100644 doc/next/6-stdlib/99-minor/net/63116.md delete mode 100644 doc/next/6-stdlib/99-minor/net/67925.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/46443.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/61472.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/62490.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/64910.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/66008.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/66343.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/66405.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/httptest/59473.md delete mode 100644 doc/next/6-stdlib/99-minor/os/33357.md delete mode 100644 doc/next/6-stdlib/99-minor/os/61893.md delete mode 100644 doc/next/6-stdlib/99-minor/os/62484.md delete mode 100644 doc/next/6-stdlib/99-minor/os/63703.md delete mode 100644 doc/next/6-stdlib/99-minor/path/filepath/57151.md delete mode 100644 doc/next/6-stdlib/99-minor/path/filepath/63703.md delete mode 100644 doc/next/6-stdlib/99-minor/reflect/60427.md delete mode 100644 doc/next/6-stdlib/99-minor/reflect/61308.md delete mode 100644 doc/next/6-stdlib/99-minor/reflect/66056.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/debug/42888.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/debug/67182.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/pprof/43669.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/trace/65319.md delete mode 100644 doc/next/6-stdlib/99-minor/slices/53987.md delete mode 100644 doc/next/6-stdlib/99-minor/slices/61899.md delete mode 100644 doc/next/6-stdlib/99-minor/slices/65238.md delete mode 100644 doc/next/6-stdlib/99-minor/structs/66408.md delete mode 100644 doc/next/6-stdlib/99-minor/sync/61696.md delete mode 100644 doc/next/6-stdlib/99-minor/sync/atomic/61395.md delete mode 100644 doc/next/6-stdlib/99-minor/syscall/62254.md delete mode 100644 doc/next/6-stdlib/99-minor/syscall/65817.md delete mode 100644 doc/next/6-stdlib/99-minor/testing/fstest/63675.md delete mode 100644 doc/next/6-stdlib/99-minor/text/template/57646.md delete mode 100644 doc/next/6-stdlib/99-minor/time/67470.md delete mode 100644 doc/next/6-stdlib/99-minor/unicode/utf16/44940.md delete mode 100644 doc/next/6-stdlib/99-minor/unique/62483.md delete mode 100644 doc/next/7-ports.md delete mode 100644 doc/next/9-todo.md diff --git a/doc/next/1-intro.md b/doc/next/1-intro.md deleted file mode 100644 index 585c6c8e52..0000000000 --- a/doc/next/1-intro.md +++ /dev/null @@ -1,14 +0,0 @@ - - - - -## DRAFT RELEASE NOTES — Introduction to Go 1.23 {#introduction} - -**Go 1.23 is not yet released. These are work-in-progress release notes. -Go 1.23 is expected to be released in August 2024.** diff --git a/doc/next/2-language.md b/doc/next/2-language.md deleted file mode 100644 index 83e3a51437..0000000000 --- a/doc/next/2-language.md +++ /dev/null @@ -1,18 +0,0 @@ -## Changes to the language {#language} - - -Go 1.23 makes the (Go 1.22) ["range-over-func" experiment](/wiki/RangefuncExperiment) a part of the language. -The "range" clause in a "for-range" loop now accepts iterator functions of the following types - - func(func() bool) - func(func(K) bool) - func(func(K, V) bool) - -as range expressions. -Calls of the iterator argument function produce the iteration values for the "for-range" loop. -For details see the [iter] package documentation and the [language spec](/ref/spec#For_range). -For motivation see the 2022 ["range-over-func" discussion](/issue/56413). - - -Go 1.23 includes preview support for [generic type aliases](/issue/46477). -Building the toolchain with `GOEXPERIMENT=aliastypeparams` enables this feature. diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md deleted file mode 100644 index 7ae651e0b4..0000000000 --- a/doc/next/3-tools.md +++ /dev/null @@ -1,84 +0,0 @@ -## Tools {#tools} - -### Telemetry - - -Starting in Go 1.23, the Go toolchain can collect usage and breakage -statistics that help the Go team understand how the Go toolchain is -used and how well it is working. We refer to these statistics as -[Go telemetry](/doc/telemetry). - -Go telemetry is an _opt-in system_, controlled by the -[`go` `telemetry` command](/cmd/go/#hdr-Manage_telemetry_data_and_settings). -By default, the toolchain programs -collect statistics in counter files that can be inspected locally -but are otherwise unused (`go` `telemetry` `local`). - -To help us keep Go working well and understand Go usage, -please consider opting in to Go telemetry by running -`go` `telemetry` `on`. -In that mode, -anonymous counter reports are uploaded to -[telemetry.go.dev](https://telemetry.go.dev) weekly, -where they are aggregated into graphs and also made -available for download by any Go contributors or users -wanting to analyze the data. -See “[Go Telemetry](/doc/telemetry)” for more details -about the Go Telemetry system. - -### Go command {#go-command} - -Setting the `GOROOT_FINAL` environment variable no longer has an effect -([#62047](/issue/62047)). -Distributions that install the `go` command to a location other than -`$GOROOT/bin/go` should install a symlink instead of relocating -or copying the `go` binary. - - -The new `go` `env` `-changed` flag causes the command to print only -those settings whose effective value differs from the default value -that would be obtained in an empty environment with no prior uses of the `-w` flag. - - -The new `go` `mod` `tidy` `-diff` flag causes the command not to modify -the files but instead print the necessary changes as a unified diff. -It exits with a non-zero code if updates are needed. - - -The `go` `list` `-m` `-json` command now includes new `Sum` and `GoModSum` fields. -This is similar to the existing behavior of the `go` `mod` `download` `-json` command. - - -The new `godebug` directive in `go.mod` and `go.work` declares a -[GODEBUG setting](/doc/godebug) to apply for the work module or workspace in use. - -### Vet {#vet} - - -The `go vet` subcommand now includes the -[stdversion](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion) -analyzer, which flags references to symbols that are too new for the version -of Go in effect in the referring file. (The effective version is determined -by the `go` directive in the file's enclosing `go.mod` file, and -by any [`//go:build` constraints](/cmd/go#hdr-Build_constraints) -in the file.) - -For example, it will report a diagnostic for a reference to the -`reflect.TypeFor` function (introduced in go1.22) from a file in a -module whose go.mod file specifies `go 1.21`. - -### Cgo {#cgo} - - -[cmd/cgo] supports the new `-ldflags` flag for passing flags to the C linker. -The `go` command uses it automatically, avoiding "argument list too long" -errors with a very large `CGO_LDFLAGS`. - -### Trace {#trace} - - -The `trace` tool now better tolerates partially broken traces by attempting to -recover what trace data it can. This functionality is particularly helpful when -viewing a trace that was collected during a program crash, since the trace data -leading up to the crash will now [be recoverable](/issue/65319) under most -circumstances. diff --git a/doc/next/4-runtime.md b/doc/next/4-runtime.md deleted file mode 100644 index 7553154a16..0000000000 --- a/doc/next/4-runtime.md +++ /dev/null @@ -1,7 +0,0 @@ -## Runtime {#runtime} - -The traceback printed by the runtime after an unhandled panic or other -fatal error now indents the second and subsequent lines of the error -message (for example, the argument to panic) by a single tab, so that -it can be unambiguously distinguished from the stack trace of the -first goroutine. See [#64590](/issue/64590) for discussion. diff --git a/doc/next/5-toolchain.md b/doc/next/5-toolchain.md deleted file mode 100644 index 51a1dbfbdf..0000000000 --- a/doc/next/5-toolchain.md +++ /dev/null @@ -1,38 +0,0 @@ -## Compiler {#compiler} - -The build time overhead to building with [Profile Guided Optimization](/doc/pgo) has been reduced significantly. -Previously, large builds could see 100%+ build time increase from enabling PGO. -In Go 1.23, overhead should be in the single digit percentages. - - -The compiler in Go 1.23 can now overlap the stack frame slots of local variables -accessed in disjoint regions of a function, which reduces stack usage -for Go applications. - - -For 386 and amd64, the compiler will use information from PGO to align certain -hot blocks in loops. This improves performance an additional 1-1.5% at -a cost of an additional 0.1% text and binary size. This is currently only implemented -on 386 and amd64 because it has not shown an improvement on other platforms. -Hot block alignment can be disabled with `-gcflags=[=]-d=alignhot=0` - -## Assembler {#assembler} - -## Linker {#linker} - - -The linker now disallows using a `//go:linkname` directive to refer to -internal symbols in the standard library (including the runtime) that -are not marked with `//go:linkname` on their definitions. -Similarly, the linker disallows references to such symbols from assembly -code. -For backward compatibility, existing usages of `//go:linkname` found in -a large open-source code corpus remain supported. -Any new references to standard library internal symbols will be disallowed. - -A linker command line flag `-checklinkname=0` can be used to disable -this check, for debugging and experimenting purposes. - - -When building a dynamically linked ELF binary (including PIE binary), the -new `-bindnow` flag enables immediate function binding. diff --git a/doc/next/6-stdlib/0-heading.md b/doc/next/6-stdlib/0-heading.md deleted file mode 100644 index 02351ce1c0..0000000000 --- a/doc/next/6-stdlib/0-heading.md +++ /dev/null @@ -1,2 +0,0 @@ -## Core library {#library} - diff --git a/doc/next/6-stdlib/1-time.md b/doc/next/6-stdlib/1-time.md deleted file mode 100644 index 6046ac5350..0000000000 --- a/doc/next/6-stdlib/1-time.md +++ /dev/null @@ -1,32 +0,0 @@ -### Timer changes - -Go 1.23 makes two significant changes to the implementation of -[time.Timer] and [time.Ticker]. - - -First, `Timer`s and `Ticker`s that are no longer referred to by the program -become eligible for garbage collection immediately, even if their -`Stop` methods have not been called. -Earlier versions of Go did not collect unstopped `Timer`s until after -they had fired and never collected unstopped `Ticker`s. - - -Second, the timer channel associated with a `Timer` or `Ticker` is -now unbuffered, with capacity 0. -The main effect of this change is that Go now guarantees -that for any call to a `Reset` or `Stop` method, no stale values -prepared before that call will be sent or received after the call. -Earlier versions of Go used channels with a one-element buffer, -making it difficult to use `Reset` and `Stop` correctly. -A visible effect of this change is that `len` and `cap` of timer channels -now returns 0 instead of 1, which may affect programs that -poll the length to decide whether a receive on the timer channel -will succeed. -Such code should use a non-blocking receive instead. - -These new behaviors are only enabled when the main Go program -is in a module with a `go.mod` `go` line using Go 1.23.0 or later. -When Go 1.23 builds older programs, the old behaviors remain in effect. -The new [GODEBUG setting](/doc/godebug) [`asynctimerchan=1`](/pkg/time/#NewTimer) -can be used to revert back to asynchronous channel behaviors -even when a program names Go 1.23.0 or later in its `go.mod` file. diff --git a/doc/next/6-stdlib/2-unique.md b/doc/next/6-stdlib/2-unique.md deleted file mode 100644 index 42737a52fa..0000000000 --- a/doc/next/6-stdlib/2-unique.md +++ /dev/null @@ -1,13 +0,0 @@ -### New unique package - -The new [unique] package provides facilities for -canonicalizing values (like "interning" or "hash-consing"). - -Any value of comparable type may be canonicalized with the new -`Make[T]` function, which produces a reference to a canonical copy of -the value in the form of a `Handle[T]`. -Two `Handle[T]` are equal if and only if the values used to produce the -handles are equal, allowing programs to deduplicate values and reduce -their memory footprint. -Comparing two `Handle[T]` values is efficient, reducing down to a simple -pointer comparison. diff --git a/doc/next/6-stdlib/3-iter.md b/doc/next/6-stdlib/3-iter.md deleted file mode 100644 index bbb3bbbd8f..0000000000 --- a/doc/next/6-stdlib/3-iter.md +++ /dev/null @@ -1,29 +0,0 @@ -### Iterators - -The new [iter] package provides the basic definitions for working with -user-defined iterators. - -The [slices] package adds several functions that work with iterators: -- [All](/pkg/slices#All) returns an iterator over slice indexes and values. -- [Values](/pkg/slices#Values) returns an iterator over slice elements. -- [Backward](/pkg/slices#Backward) returns an iterator that loops over - a slice backward. -- [Collect](/pkg/slices#Collect) collects values from an iterator into - a new slice. -- [AppendSeq](/pkg/slices#AppendSeq) appends values from an iterator to - an existing slice. -- [Sorted](/pkg/slices#Sorted) collects values from an iterator into a - new slice, and then sorts the slice. -- [SortedFunc](/pkg/slices#SortedFunc) is like `Sorted` but with a - comparison function. -- [SortedStableFunc](/pkg/slices#SortedStableFunc) is like `SortFunc` - but uses a stable sort algorithm. -- [Chunk](/pkg/slices#Chunk) returns an iterator over consecutive - sub-slices of up to n elements of a slice. - -The [maps] package adds several functions that work with iterators: -- [All](/pkg/maps#All) returns an iterator over key-value pairs from a map. -- [Keys](/pkg/maps#Keys) returns an iterator over keys in a map. -- [Values](/pkg/maps#Values) returns an iterator over values in a map. -- [Insert](/pkg/maps#Insert) adds the key-value pairs from an iterator to an existing map. -- [Collect](/pkg/maps#Collect) collects key-value pairs from an iterator into a new map and returns it. diff --git a/doc/next/6-stdlib/4-structs.md b/doc/next/6-stdlib/4-structs.md deleted file mode 100644 index adf42f1b37..0000000000 --- a/doc/next/6-stdlib/4-structs.md +++ /dev/null @@ -1,11 +0,0 @@ -### New structs package - -The new [structs] package provides -types for struct fields that modify properties of -the containing struct type such as memory layout. - -In this release, the only such type is -[`HostLayout`](/pkg/structs#HostLayout) -which indicates that a structure with a field of that -type has a layout that conforms to host platform -expectations. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/0-heading.md b/doc/next/6-stdlib/99-minor/0-heading.md deleted file mode 100644 index a98105e8cc..0000000000 --- a/doc/next/6-stdlib/99-minor/0-heading.md +++ /dev/null @@ -1,3 +0,0 @@ -### Minor changes to the library {#minor_library_changes} - - diff --git a/doc/next/6-stdlib/99-minor/README b/doc/next/6-stdlib/99-minor/README deleted file mode 100644 index fac778de05..0000000000 --- a/doc/next/6-stdlib/99-minor/README +++ /dev/null @@ -1 +0,0 @@ -API changes and other small changes to the standard library go here. diff --git a/doc/next/6-stdlib/99-minor/archive/tar/50102.md b/doc/next/6-stdlib/99-minor/archive/tar/50102.md deleted file mode 100644 index ed8675f693..0000000000 --- a/doc/next/6-stdlib/99-minor/archive/tar/50102.md +++ /dev/null @@ -1,4 +0,0 @@ -If the argument to [FileInfoHeader] implements the new [FileInfoNames] -interface, then the interface methods will be used to set the Uname/Gname -of the file header. This allows applications to override the system-dependent -Uname/Gname lookup. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/63369.md b/doc/next/6-stdlib/99-minor/crypto/tls/63369.md deleted file mode 100644 index 6ec5b5bdf6..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/63369.md +++ /dev/null @@ -1,3 +0,0 @@ -The TLS client now supports the Encrypted Client Hello [draft specification](https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html). -This feature can be enabled by setting the [Config.EncryptedClientHelloConfigList] -field to an encoded ECHConfigList for the host that is being connected to. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/63691.md b/doc/next/6-stdlib/99-minor/crypto/tls/63691.md deleted file mode 100644 index 67ed04cf00..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/63691.md +++ /dev/null @@ -1,3 +0,0 @@ -The [QUICConn] type used by QUIC implementations includes new events -reporting on the state of session resumption, and provides a way for -the QUIC layer to add data to session tickets and session cache entries. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/66214.md b/doc/next/6-stdlib/99-minor/crypto/tls/66214.md deleted file mode 100644 index ebe1b490f5..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/66214.md +++ /dev/null @@ -1,3 +0,0 @@ -3DES cipher suites were removed from the default list used when -[Config.CipherSuites] is nil. The default can be reverted by adding `tls3des=1` to -the GODEBUG environment variable. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/67061.md b/doc/next/6-stdlib/99-minor/crypto/tls/67061.md deleted file mode 100644 index fe3620ed6d..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/67061.md +++ /dev/null @@ -1,3 +0,0 @@ -The experimental post-quantum key exchange mechanism X25519Kyber768Draft00 -is now enabled by default when [Config.CurvePreferences] is nil. -The default can be reverted by adding `tlskyber=0` to the GODEBUG environment variable. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/67065.md b/doc/next/6-stdlib/99-minor/crypto/tls/67065.md deleted file mode 100644 index 3fcc8d5309..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/67065.md +++ /dev/null @@ -1,3 +0,0 @@ -Go 1.23 changed the behavior of [X509KeyPair] and [LoadX509KeyPair] -to populate the [Certificate.Leaf] field of the returned [Certificate]. -The new `x509keypairleaf` [GODEBUG setting](/doc/godebug) is added for this behavior. diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/45990.md b/doc/next/6-stdlib/99-minor/crypto/x509/45990.md deleted file mode 100644 index 2eda8476a9..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/x509/45990.md +++ /dev/null @@ -1,3 +0,0 @@ -[CreateCertificateRequest] now correct supports RSA-PSS signature algorithms. - -[CreateCertificateRequest] and [CreateRevocationList] now verify the generated signature using the signer’s public key. If the signature is invalid, an error is returned. This has been the behavior of [CreateCertificate] since Go 1.16. diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/62048.md b/doc/next/6-stdlib/99-minor/crypto/x509/62048.md deleted file mode 100644 index aaa8c5e350..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/x509/62048.md +++ /dev/null @@ -1,4 +0,0 @@ -The [`x509sha1` GODEBUG setting](/pkg/crypto/x509#InsecureAlgorithmError) will -be removed in the next Go major release (Go 1.24). This will mean that crypto/x509 -will no longer support verifying signatures on certificates that use SHA-1 based -signature algorithms. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/66249.md b/doc/next/6-stdlib/99-minor/crypto/x509/66249.md deleted file mode 100644 index d449e74d66..0000000000 --- a/doc/next/6-stdlib/99-minor/crypto/x509/66249.md +++ /dev/null @@ -1,3 +0,0 @@ -The new [ParseOID] function parses a dot-encoded ASN.1 Object Identifier string. -The [OID] type now implements the [encoding.BinaryMarshaler], -[encoding.BinaryUnmarshaler], [encoding.TextMarshaler], [encoding.TextUnmarshaler] interfaces. diff --git a/doc/next/6-stdlib/99-minor/database/sql/64707.md b/doc/next/6-stdlib/99-minor/database/sql/64707.md deleted file mode 100644 index 17d4516ba8..0000000000 --- a/doc/next/6-stdlib/99-minor/database/sql/64707.md +++ /dev/null @@ -1,3 +0,0 @@ -Errors returned by [driver.Valuer] implementations are now wrapped for -improved error handling during operations like [DB.Query], [DB.Exec], -and [DB.QueryRow]. diff --git a/doc/next/6-stdlib/99-minor/debug/elf/66054.md b/doc/next/6-stdlib/99-minor/debug/elf/66054.md deleted file mode 100644 index 0b3443f7d4..0000000000 --- a/doc/next/6-stdlib/99-minor/debug/elf/66054.md +++ /dev/null @@ -1,3 +0,0 @@ -The `debug/elf` package now defines [PT_OPENBSD_NOBTCFI]. This [ProgType] is -used to disable Branch Tracking Control Flow Integrity (BTCFI) enforcement -on OpenBSD binaries. diff --git a/doc/next/6-stdlib/99-minor/debug/elf/66836.md b/doc/next/6-stdlib/99-minor/debug/elf/66836.md deleted file mode 100644 index 4aad5798dd..0000000000 --- a/doc/next/6-stdlib/99-minor/debug/elf/66836.md +++ /dev/null @@ -1,2 +0,0 @@ -Now defines the symbol type constants [STT_RELC], [STT_SRELC], and -[STT_GNU_IFUNC]. diff --git a/doc/next/6-stdlib/99-minor/encoding/binary/60023.md b/doc/next/6-stdlib/99-minor/encoding/binary/60023.md deleted file mode 100644 index 015bfc3803..0000000000 --- a/doc/next/6-stdlib/99-minor/encoding/binary/60023.md +++ /dev/null @@ -1,3 +0,0 @@ -The new [Encode] and [Decode] functions are byte slice equivalents -to [Read] and [Write]. -[Append] allows marshaling multiple data into the same byte slice. diff --git a/doc/next/6-stdlib/99-minor/go/ast/66339.md b/doc/next/6-stdlib/99-minor/go/ast/66339.md deleted file mode 100644 index 0eec51ecd6..0000000000 --- a/doc/next/6-stdlib/99-minor/go/ast/66339.md +++ /dev/null @@ -1,2 +0,0 @@ -The new [Preorder] function returns a convenient iterator over all the -nodes of a syntax tree. diff --git a/doc/next/6-stdlib/99-minor/go/types/46477.md b/doc/next/6-stdlib/99-minor/go/types/46477.md deleted file mode 100644 index 7f744dc6ae..0000000000 --- a/doc/next/6-stdlib/99-minor/go/types/46477.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/go/types/65772.md b/doc/next/6-stdlib/99-minor/go/types/65772.md deleted file mode 100644 index ec7f0b0e59..0000000000 --- a/doc/next/6-stdlib/99-minor/go/types/65772.md +++ /dev/null @@ -1,3 +0,0 @@ -The [Func] type, which represents a function or method symbol, now -has a [Func.Signature] method that returns the function's type, which -is always a `Signature`. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/go/types/66559.md b/doc/next/6-stdlib/99-minor/go/types/66559.md deleted file mode 100644 index e3884594fa..0000000000 --- a/doc/next/6-stdlib/99-minor/go/types/66559.md +++ /dev/null @@ -1,3 +0,0 @@ -The [Alias] type now has an [Rhs] method that returns the type on the -right-hand side of its declaration: given `type A = B`, the `Rhs` of A -is B. ([#66559](/issue/66559)) diff --git a/doc/next/6-stdlib/99-minor/go/types/67143.md b/doc/next/6-stdlib/99-minor/go/types/67143.md deleted file mode 100644 index 405c679378..0000000000 --- a/doc/next/6-stdlib/99-minor/go/types/67143.md +++ /dev/null @@ -1,2 +0,0 @@ -The methods [Alias.Origin], [Alias.SetTypeParams], [Alias.TypeParams], -and [Alias.TypeArgs] have been added. They are needed for generic alias types. diff --git a/doc/next/6-stdlib/99-minor/go/types/cl-577715.md b/doc/next/6-stdlib/99-minor/go/types/cl-577715.md deleted file mode 100644 index 939d5ac46c..0000000000 --- a/doc/next/6-stdlib/99-minor/go/types/cl-577715.md +++ /dev/null @@ -1,4 +0,0 @@ - -By default, go/types now produces [Alias] type nodes for type aliases. -This behavior can be controlled by the `GODEBUG` `gotypesalias` flag. -Its default has changed from 0 in Go 1.22 to 1 in Go 1.23. diff --git a/doc/next/6-stdlib/99-minor/iter/61897.md b/doc/next/6-stdlib/99-minor/iter/61897.md deleted file mode 100644 index 02d77cd11d..0000000000 --- a/doc/next/6-stdlib/99-minor/iter/61897.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/maps/61900.md b/doc/next/6-stdlib/99-minor/maps/61900.md deleted file mode 100644 index 02d77cd11d..0000000000 --- a/doc/next/6-stdlib/99-minor/maps/61900.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/math/rand/v2/61716.md b/doc/next/6-stdlib/99-minor/math/rand/v2/61716.md deleted file mode 100644 index 68ff614ee5..0000000000 --- a/doc/next/6-stdlib/99-minor/math/rand/v2/61716.md +++ /dev/null @@ -1,2 +0,0 @@ -The [Uint] function and [Rand.Uint] method have been added. -They were inadvertently left out of Go 1.22. diff --git a/doc/next/6-stdlib/99-minor/math/rand/v2/67059.md b/doc/next/6-stdlib/99-minor/math/rand/v2/67059.md deleted file mode 100644 index c66110c7a4..0000000000 --- a/doc/next/6-stdlib/99-minor/math/rand/v2/67059.md +++ /dev/null @@ -1 +0,0 @@ -The new [ChaCha8.Read] method implements the [io.Reader] interface. diff --git a/doc/next/6-stdlib/99-minor/net/62254.md b/doc/next/6-stdlib/99-minor/net/62254.md deleted file mode 100644 index 639140bbec..0000000000 --- a/doc/next/6-stdlib/99-minor/net/62254.md +++ /dev/null @@ -1,3 +0,0 @@ -The new type [KeepAliveConfig] permits fine-tuning the keep-alive -options for TCP connections, via a new [TCPConn.SetKeepAliveConfig] -method and new KeepAliveConfig fields for [Dialer] and [ListenConfig]. diff --git a/doc/next/6-stdlib/99-minor/net/63116.md b/doc/next/6-stdlib/99-minor/net/63116.md deleted file mode 100644 index 87a0983749..0000000000 --- a/doc/next/6-stdlib/99-minor/net/63116.md +++ /dev/null @@ -1,3 +0,0 @@ -The [DNSError] type now wraps errors caused by timeouts or cancellation. -For example, `errors.Is(someDNSErr, context.DeadlineExceedeed)` -will now report whether a DNS error was caused by a timeout. diff --git a/doc/next/6-stdlib/99-minor/net/67925.md b/doc/next/6-stdlib/99-minor/net/67925.md deleted file mode 100644 index e43f0cd644..0000000000 --- a/doc/next/6-stdlib/99-minor/net/67925.md +++ /dev/null @@ -1,3 +0,0 @@ -The new `GODEBUG` setting `netedns0=0` disables sending EDNS0 -additional headers on DNS requests, as they reportedly break the DNS -server on some modems. diff --git a/doc/next/6-stdlib/99-minor/net/http/46443.md b/doc/next/6-stdlib/99-minor/net/http/46443.md deleted file mode 100644 index 37ceae9edd..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/46443.md +++ /dev/null @@ -1,3 +0,0 @@ -[Cookie] now preserves double quotes surrounding a cookie value. -The new [Cookie.Quoted] field indicates whether the [Cookie.Value] -was originally quoted. diff --git a/doc/next/6-stdlib/99-minor/net/http/61472.md b/doc/next/6-stdlib/99-minor/net/http/61472.md deleted file mode 100644 index b3c2fd5409..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/61472.md +++ /dev/null @@ -1 +0,0 @@ -The new [Request.CookiesNamed] method retrieves all cookies that match the given name. diff --git a/doc/next/6-stdlib/99-minor/net/http/62490.md b/doc/next/6-stdlib/99-minor/net/http/62490.md deleted file mode 100644 index 891eb45dae..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/62490.md +++ /dev/null @@ -1 +0,0 @@ -The new [Cookie.Partitioned] field identifies cookies with the Partitioned attribute. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/net/http/64910.md b/doc/next/6-stdlib/99-minor/net/http/64910.md deleted file mode 100644 index 28452ee932..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/64910.md +++ /dev/null @@ -1,2 +0,0 @@ -The patterns used by [ServeMux] now allow one or more spaces or tabs after the method name. -Previously, only a single space was permitted. diff --git a/doc/next/6-stdlib/99-minor/net/http/66008.md b/doc/next/6-stdlib/99-minor/net/http/66008.md deleted file mode 100644 index e8603707ef..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/66008.md +++ /dev/null @@ -1,7 +0,0 @@ -The new [ParseCookie] function parses a Cookie header value and -returns all the cookies which were set in it. Since the same cookie -name can appear multiple times the returned Values can contain -more than one value for a given key. - -The new [ParseSetCookie] function parses a Set-Cookie header value and -returns a cookie. It returns an error on syntax error. diff --git a/doc/next/6-stdlib/99-minor/net/http/66343.md b/doc/next/6-stdlib/99-minor/net/http/66343.md deleted file mode 100644 index b39e8624e7..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/66343.md +++ /dev/null @@ -1,16 +0,0 @@ -[ServeContent], [ServeFile], and [ServeFileFS] now remove -the `Cache-Control`, `Content-Encoding`, `Etag`, and `Last-Modified` -headers when serving an error. These headers usually apply to the -non-error content, but not to the text of errors. - -Middleware which wraps a [ResponseWriter] and applies on-the-fly -encoding, such as `Content-Encoding: gzip`, will not function after -this change. The previous behavior of [ServeContent], [ServeFile], -and [ServeFileFS] may be restored by setting -`GODEBUG=httpservecontentkeepheaders=1`. - -Note that middleware which changes the size of the served content -(such as by compressing it) already does not function properly when -[ServeContent] handles a Range request. On-the-fly compression -should use the `Transfer-Encoding` header instead of `Content-Encoding`. - diff --git a/doc/next/6-stdlib/99-minor/net/http/66405.md b/doc/next/6-stdlib/99-minor/net/http/66405.md deleted file mode 100644 index c827b4b219..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/66405.md +++ /dev/null @@ -1,3 +0,0 @@ -For inbound requests, the new [Request.Pattern] field contains the [ServeMux] -pattern (if any) that matched the request. This field is not set when -`GODEBUG=httpmuxgo121=1` is set. diff --git a/doc/next/6-stdlib/99-minor/net/http/httptest/59473.md b/doc/next/6-stdlib/99-minor/net/http/httptest/59473.md deleted file mode 100644 index a640bbd0e4..0000000000 --- a/doc/next/6-stdlib/99-minor/net/http/httptest/59473.md +++ /dev/null @@ -1,2 +0,0 @@ -The new [NewRequestWithContext] method creates an incoming request with -a [context.Context]. diff --git a/doc/next/6-stdlib/99-minor/os/33357.md b/doc/next/6-stdlib/99-minor/os/33357.md deleted file mode 100644 index bd542d9d77..0000000000 --- a/doc/next/6-stdlib/99-minor/os/33357.md +++ /dev/null @@ -1,3 +0,0 @@ -The [Stat] function now sets the [ModeSocket] bit for -files that are Unix sockets on Windows. These files are identified -by having a reparse tag set to `IO_REPARSE_TAG_AF_UNIX`. diff --git a/doc/next/6-stdlib/99-minor/os/61893.md b/doc/next/6-stdlib/99-minor/os/61893.md deleted file mode 100644 index d22060c869..0000000000 --- a/doc/next/6-stdlib/99-minor/os/61893.md +++ /dev/null @@ -1,7 +0,0 @@ -On Windows, the mode bits reported by [Lstat] and [Stat] for -reparse points changed. Mount points no longer have [ModeSymlink] set, -and reparse points that are not symlinks, Unix sockets, or dedup files -now always have [ModeIrregular] set. -This behavior is controlled by the `winsymlink` setting. -For Go 1.23, it defaults to `winsymlink=1`. -Previous versions default to `winsymlink=0`. diff --git a/doc/next/6-stdlib/99-minor/os/62484.md b/doc/next/6-stdlib/99-minor/os/62484.md deleted file mode 100644 index c99801bb6c..0000000000 --- a/doc/next/6-stdlib/99-minor/os/62484.md +++ /dev/null @@ -1 +0,0 @@ -The [CopyFS] function copies an [io/fs.FS] into the local filesystem. diff --git a/doc/next/6-stdlib/99-minor/os/63703.md b/doc/next/6-stdlib/99-minor/os/63703.md deleted file mode 100644 index 3fbb2594cf..0000000000 --- a/doc/next/6-stdlib/99-minor/os/63703.md +++ /dev/null @@ -1,5 +0,0 @@ -On Windows, [Readlink] no longer tries to normalize volumes -to drive letters, which was not always even possible. -This behavior is controlled by the `winreadlinkvolume` setting. -For Go 1.23, it defaults to `winreadlinkvolume=1`. -Previous versions default to `winreadlinkvolume=0`. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/path/filepath/57151.md b/doc/next/6-stdlib/99-minor/path/filepath/57151.md deleted file mode 100644 index 5a99e3a4f2..0000000000 --- a/doc/next/6-stdlib/99-minor/path/filepath/57151.md +++ /dev/null @@ -1,2 +0,0 @@ -The new [Localize] function safely converts a slash-separated -path into an operating system path. diff --git a/doc/next/6-stdlib/99-minor/path/filepath/63703.md b/doc/next/6-stdlib/99-minor/path/filepath/63703.md deleted file mode 100644 index da2b132d8b..0000000000 --- a/doc/next/6-stdlib/99-minor/path/filepath/63703.md +++ /dev/null @@ -1,11 +0,0 @@ -On Windows, [EvalSymlinks] no longer evaluates mount points, -which was a source of many inconsistencies and bugs. -This behavior is controlled by the `winsymlink` setting. -For Go 1.23, it defaults to `winsymlink=1`. -Previous versions default to `winsymlink=0`. - -On Windows, [EvalSymlinks] no longer tries to normalize -volumes to drive letters, which was not always even possible. -This behavior is controlled by the `winreadlinkvolume` setting. -For Go 1.23, it defaults to `winreadlinkvolume=1`. -Previous versions default to `winreadlinkvolume=0`. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/reflect/60427.md b/doc/next/6-stdlib/99-minor/reflect/60427.md deleted file mode 100644 index bca1360734..0000000000 --- a/doc/next/6-stdlib/99-minor/reflect/60427.md +++ /dev/null @@ -1,6 +0,0 @@ -The new methods synonymous with the method of the same name -in [Value] are added to [Type]: -1. [Type.OverflowComplex] -2. [Type.OverflowFloat] -3. [Type.OverflowInt] -4. [Type.OverflowUint] diff --git a/doc/next/6-stdlib/99-minor/reflect/61308.md b/doc/next/6-stdlib/99-minor/reflect/61308.md deleted file mode 100644 index ec24655dce..0000000000 --- a/doc/next/6-stdlib/99-minor/reflect/61308.md +++ /dev/null @@ -1,3 +0,0 @@ -The new [SliceAt] function is analogous to [NewAt], but for slices. - -The [Value.Pointer] and [Value.UnsafePointer] methods now support values of kind [String]. diff --git a/doc/next/6-stdlib/99-minor/reflect/66056.md b/doc/next/6-stdlib/99-minor/reflect/66056.md deleted file mode 100644 index b5f39349df..0000000000 --- a/doc/next/6-stdlib/99-minor/reflect/66056.md +++ /dev/null @@ -1,4 +0,0 @@ -The new methods [Value.Seq] and [Value.Seq2] return sequences that iterate over the value -as though it were used in a for/range loop. -The new methods [Type.CanSeq] and [Type.CanSeq2] report whether calling -[Value.Seq] and [Value.Seq2], respectively, will succeed without panicking. diff --git a/doc/next/6-stdlib/99-minor/runtime/debug/42888.md b/doc/next/6-stdlib/99-minor/runtime/debug/42888.md deleted file mode 100644 index f10753d25c..0000000000 --- a/doc/next/6-stdlib/99-minor/runtime/debug/42888.md +++ /dev/null @@ -1,5 +0,0 @@ -The [SetCrashOutput] function allows the user to specify an alternate -file to which the runtime should write its fatal crash report. -It may be used to construct an automated reporting mechanism for all -unexpected crashes, not just those in goroutines that explicitly use -`recover`. diff --git a/doc/next/6-stdlib/99-minor/runtime/debug/67182.md b/doc/next/6-stdlib/99-minor/runtime/debug/67182.md deleted file mode 100644 index d83864a3db..0000000000 --- a/doc/next/6-stdlib/99-minor/runtime/debug/67182.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/runtime/pprof/43669.md b/doc/next/6-stdlib/99-minor/runtime/pprof/43669.md deleted file mode 100644 index 119308b46a..0000000000 --- a/doc/next/6-stdlib/99-minor/runtime/pprof/43669.md +++ /dev/null @@ -1,2 +0,0 @@ -The maximum stack depth for alloc, mutex, block, threadcreate and goroutine -profiles has been raised from 32 to 128 frames. diff --git a/doc/next/6-stdlib/99-minor/runtime/trace/65319.md b/doc/next/6-stdlib/99-minor/runtime/trace/65319.md deleted file mode 100644 index b180368e00..0000000000 --- a/doc/next/6-stdlib/99-minor/runtime/trace/65319.md +++ /dev/null @@ -1,4 +0,0 @@ - -The runtime now explicitly flushes trace data when a program crashes due to an -uncaught panic. This means that more complete trace data will be available in a -trace if the program crashes while tracing is active. diff --git a/doc/next/6-stdlib/99-minor/slices/53987.md b/doc/next/6-stdlib/99-minor/slices/53987.md deleted file mode 100644 index 02d77cd11d..0000000000 --- a/doc/next/6-stdlib/99-minor/slices/53987.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/slices/61899.md b/doc/next/6-stdlib/99-minor/slices/61899.md deleted file mode 100644 index 02d77cd11d..0000000000 --- a/doc/next/6-stdlib/99-minor/slices/61899.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/slices/65238.md b/doc/next/6-stdlib/99-minor/slices/65238.md deleted file mode 100644 index 34ef66a2dd..0000000000 --- a/doc/next/6-stdlib/99-minor/slices/65238.md +++ /dev/null @@ -1,2 +0,0 @@ -The [Repeat] function returns a new slice that repeats the -provided slice the given number of times. diff --git a/doc/next/6-stdlib/99-minor/structs/66408.md b/doc/next/6-stdlib/99-minor/structs/66408.md deleted file mode 100644 index 810a09e3ca..0000000000 --- a/doc/next/6-stdlib/99-minor/structs/66408.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/sync/61696.md b/doc/next/6-stdlib/99-minor/sync/61696.md deleted file mode 100644 index 59584301f3..0000000000 --- a/doc/next/6-stdlib/99-minor/sync/61696.md +++ /dev/null @@ -1,2 +0,0 @@ -The [Map.Clear] method deletes all the entries, resulting in -an empty [Map]. It is analogous to `clear`. diff --git a/doc/next/6-stdlib/99-minor/sync/atomic/61395.md b/doc/next/6-stdlib/99-minor/sync/atomic/61395.md deleted file mode 100644 index 8aea9d6bf3..0000000000 --- a/doc/next/6-stdlib/99-minor/sync/atomic/61395.md +++ /dev/null @@ -1,3 +0,0 @@ - -The new [And] and [Or] operators apply a bitwise `AND` or `OR` to -the given input, returning the old value. diff --git a/doc/next/6-stdlib/99-minor/syscall/62254.md b/doc/next/6-stdlib/99-minor/syscall/62254.md deleted file mode 100644 index 1d463e5ea8..0000000000 --- a/doc/next/6-stdlib/99-minor/syscall/62254.md +++ /dev/null @@ -1 +0,0 @@ -The syscall package now defines [WSAENOPROTOOPT] on Windows. diff --git a/doc/next/6-stdlib/99-minor/syscall/65817.md b/doc/next/6-stdlib/99-minor/syscall/65817.md deleted file mode 100644 index 9a2d12c074..0000000000 --- a/doc/next/6-stdlib/99-minor/syscall/65817.md +++ /dev/null @@ -1 +0,0 @@ -The [GetsockoptInt] function is now supported on Windows. diff --git a/doc/next/6-stdlib/99-minor/testing/fstest/63675.md b/doc/next/6-stdlib/99-minor/testing/fstest/63675.md deleted file mode 100644 index cea9ae3dc2..0000000000 --- a/doc/next/6-stdlib/99-minor/testing/fstest/63675.md +++ /dev/null @@ -1,3 +0,0 @@ -[TestFS] now returns a structured error that can be unwrapped -(via method `Unwrap() []error`). This allows inspecting errors -using [errors.Is] or [errors.As]. diff --git a/doc/next/6-stdlib/99-minor/text/template/57646.md b/doc/next/6-stdlib/99-minor/text/template/57646.md deleted file mode 100644 index 5b8f031432..0000000000 --- a/doc/next/6-stdlib/99-minor/text/template/57646.md +++ /dev/null @@ -1 +0,0 @@ -Templates now support the new "else with" action, which reduces template complexity in some use cases. diff --git a/doc/next/6-stdlib/99-minor/time/67470.md b/doc/next/6-stdlib/99-minor/time/67470.md deleted file mode 100644 index 8cfcc0aa9d..0000000000 --- a/doc/next/6-stdlib/99-minor/time/67470.md +++ /dev/null @@ -1,2 +0,0 @@ -[Parse] and [ParseInLocation] now return an error if the time zone -offset is out of range. diff --git a/doc/next/6-stdlib/99-minor/unicode/utf16/44940.md b/doc/next/6-stdlib/99-minor/unicode/utf16/44940.md deleted file mode 100644 index e066784588..0000000000 --- a/doc/next/6-stdlib/99-minor/unicode/utf16/44940.md +++ /dev/null @@ -1,3 +0,0 @@ -The [RuneLen] function returns the number of 16-bit words in -the UTF-16 encoding of the rune. It returns -1 if the rune -is not a valid value to encode in UTF-16. diff --git a/doc/next/6-stdlib/99-minor/unique/62483.md b/doc/next/6-stdlib/99-minor/unique/62483.md deleted file mode 100644 index d281ab290e..0000000000 --- a/doc/next/6-stdlib/99-minor/unique/62483.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/7-ports.md b/doc/next/7-ports.md deleted file mode 100644 index 51e0ac7441..0000000000 --- a/doc/next/7-ports.md +++ /dev/null @@ -1,38 +0,0 @@ -## Ports {#ports} - -### Darwin {#darwin} - - -As [announced](go1.22#darwin) in the Go 1.22 release notes, -Go 1.23 requires macOS 11 Big Sur or later; -support for previous versions has been discontinued. - -### Linux {#linux} - - -Go 1.23 is the last release that requires Linux kernel version 2.6.32 or later. Go 1.24 will require Linux kernel version 3.17 or later, with an exception that systems running 3.10 or later will continue to be supported if the kernel has been patched to support the getrandom system call. - -### OpenBSD {#openbsd} - - -Go 1.23 adds experimental support for OpenBSD on 64-bit RISC-V (`GOOS=openbsd`, `GOARCH=riscv64`). - -### ARM64 {#arm64} - - -Go 1.23 introduces a new `GOARM64` environment variable, which specifies the minimum target version of the ARM64 architecture at compile time. Allowed values are `v8.{0-9}` and `v9.{0-5}`. This may be followed by an option specifying extensions implemented by target hardware. Valid options are `,lse` and `,crypto`. - -The `GOARM64` environment variable defaults to `v8.0`. - -### RISC-V {#riscv} - - -Go 1.23 introduces a new `GORISCV64` environment variable, which selects the [RISC-V user-mode application profile](https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc) for which to compile. Allowed values are `rva20u64` and `rva22u64`. - -The `GORISCV64` environment variable defaults to `rva20u64`. - -### Wasm {#wasm} - - -The `go_wasip1_wasm_exec` script in `GOROOT/misc/wasm` has dropped support -for versions of `wasmtime` < 14.0.0. diff --git a/doc/next/9-todo.md b/doc/next/9-todo.md deleted file mode 100644 index 424780cd7d..0000000000 --- a/doc/next/9-todo.md +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - From 0af2148fdcd047e5aa15776a54ccc29d9aa36f7f Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 21 Jun 2024 16:32:37 -0400 Subject: [PATCH 16/72] cmd: vendor golang.org/x/telemetry@a740542 Commands run: go get golang.org/x/telemetry@a740542 go mod tidy go mod vendor Change-Id: I8b1a71adc05f3c54f9492dfb9cfd1873727e5680 Reviewed-on: https://go-review.googlesource.com/c/go/+/594017 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +-- .../golang.org/x/telemetry/counter/counter.go | 4 --- .../x/telemetry/internal/counter/file.go | 35 +++++++++++-------- src/cmd/vendor/modules.txt | 2 +- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 0625195931..0a17a414b5 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -9,7 +9,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 + golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 25276c92b2..49849d10b4 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,8 +16,8 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 h1:2+8QyQRLYDeEKd+CM/BsuaBaLdhAsNdasS/SnZfPS9g= -golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c h1:zNxtD9mZQCgRwCNanVRlJ/XlOyATHcbR+09LzoArRl4= +golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go index 7a7e66b22d..ff727ad97c 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go +++ b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go @@ -83,8 +83,6 @@ func NewStack(name string, depth int) *StackCounter { // If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the // counter file on disk and starts to mmap telemetry counters to the file. // Open also persists any counters already created in the current process. -// -// Programs using telemetry should call either Open or OpenDir exactly once. func Open() { counter.Open() } @@ -95,8 +93,6 @@ func Open() { // If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the // counter file on disk and starts to mmap telemetry counters to the file. // Open also persists any counters already created in the current process. -// -// Programs using telemetry should call either Open or OpenDir exactly once. func OpenDir(telemetryDir string) { if telemetryDir != "" { telemetry.Default = telemetry.NewDir(telemetryDir) diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go index 0cb6cc22de..e3c574dcb4 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -340,6 +340,8 @@ func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { return v, cleanup } +var openOnce sync.Once + // Open associates counting with the defaultFile. // The returned function is for testing only, and should // be called after all Inc()s are finished, but before @@ -349,22 +351,27 @@ func Open() func() { if telemetry.DisabledOnPlatform { return func() {} } - if mode, _ := telemetry.Default.Mode(); mode == "off" { - // Don't open the file when telemetry is off. - defaultFile.err = ErrDisabled - return func() {} // No need to clean up. - } - debugPrintf("Open") - defaultFile.rotate() - return func() { - // Once this has been called, the defaultFile is no longer usable. - mf := defaultFile.current.Load() - if mf == nil { - // telemetry might have been off + close := func() {} + openOnce.Do(func() { + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // Don't open the file when telemetry is off. + defaultFile.err = ErrDisabled + // No need to clean up. return } - mf.close() - } + debugPrintf("Open") + defaultFile.rotate() + close = func() { + // Once this has been called, the defaultFile is no longer usable. + mf := defaultFile.current.Load() + if mf == nil { + // telemetry might have been off + return + } + mf.close() + } + }) + return close } // A mappedFile is a counter file mmapped into memory. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index fc1f25588a..5184adb1f2 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -45,7 +45,7 @@ golang.org/x/sync/semaphore golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 +# golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter From 44f18706661db8b865719d15a5cfa0515d1a4fca Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 17 Jun 2024 14:44:42 -0400 Subject: [PATCH 17/72] cmd/link: handle dynamic import variables on Darwin in plugin mode CL 501855 added support for cgo_dynamic_import variables on Darwin. But it didn't support the plugin build mode on amd64, where the assembler turns a direct load (R_PCREL) to a load via GOT (R_GOTPCREL). This CL adds the support. We just need to handle external linking mode, as this can only occur in plugin or shared build mode, which requires external linking. Fixes #67976. Updates #50891. Change-Id: I0f56265d50bfcb36047fa5538ad7a5ec77e7ef96 Reviewed-on: https://go-review.googlesource.com/c/go/+/592499 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/cmd/cgo/internal/testplugin/plugin_test.go | 8 ++++++++ .../testplugin/testdata/issue67976/plugin.go | 16 ++++++++++++++++ src/cmd/link/internal/amd64/asm.go | 7 +++++++ 3 files changed, 31 insertions(+) create mode 100644 src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go diff --git a/src/cmd/cgo/internal/testplugin/plugin_test.go b/src/cmd/cgo/internal/testplugin/plugin_test.go index 4900ada182..85dfd31123 100644 --- a/src/cmd/cgo/internal/testplugin/plugin_test.go +++ b/src/cmd/cgo/internal/testplugin/plugin_test.go @@ -414,3 +414,11 @@ func TestTextSectionSplit(t *testing.T) { t.Errorf("runtime.text.1 not found, text section not split?") } } + +func TestIssue67976(t *testing.T) { + // Issue 67976: build failure with loading a dynimport variable (the runtime/pprof + // package does this on darwin) in a plugin on darwin/amd64. + // The test program uses runtime/pprof in a plugin. + globalSkip(t) + goCmd(t, "build", "-buildmode=plugin", "-o", "issue67976.so", "./issue67976/plugin.go") +} diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go b/src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go new file mode 100644 index 0000000000..502ecc5c47 --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go @@ -0,0 +1,16 @@ +// Copyright 2024 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 main + +import ( + "io" + "runtime/pprof" +) + +func main() {} + +func Start() { + pprof.StartCPUProfile(io.Discard) +} diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index f86d224932..9da0541f52 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -398,6 +398,13 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade // (e.g. go version). return true } + case objabi.R_GOTPCREL: + if target.IsExternal() { + // External linker will do this relocation. + return true + } + // We only need to handle external linking mode, as R_GOTPCREL can + // only occur in plugin or shared build modes. } return false From e8ee1dc4f9e2632ba1018610d1a1187743ae397f Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Fri, 21 Jun 2024 16:44:44 -0700 Subject: [PATCH 18/72] cmd/link/internal/ld: handle "\r" in MinGW "--print-prog-name" output Fix the "gcc --print-prog-name" output parser to handle "\r\n", not only "\n". The MinGW compiler on Windows uses "\r\n" as line endings, causing the existing parser to create paths like ".../x86_64-w64-mingw32/bin/ar.exe\r", which is not correct. By trimming the "\r\n" cutset, both types of line endings are handled correctly. Fixes #68121 Change-Id: I04b8bf9b6a5b29a1e59a6aa07fa4faa4c5bdeee6 Reviewed-on: https://go-review.googlesource.com/c/go/+/593916 LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui Commit-Queue: Ian Lance Taylor --- src/cmd/link/internal/ld/lib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 3bec04e0b8..c29a532bfd 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2917,6 +2917,6 @@ func (ctxt *Link) findExtLinkTool(toolname string) string { if err != nil { Exitf("%s: finding %s failed: %v\n%s", os.Args[0], toolname, err, out) } - cmdpath := strings.TrimSuffix(string(out), "\n") + cmdpath := strings.TrimRight(string(out), "\r\n") return cmdpath } From 740043f516f716fe359ffd3bd76f1a30a9aa5eec Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 23 Jun 2024 15:21:28 -0700 Subject: [PATCH 19/72] net/netip: unexport fields of addrDetail For #68113 Change-Id: I19c7d8eff8e3a7a1b6c8e28cb867edeca6be237d Reviewed-on: https://go-review.googlesource.com/c/go/+/593737 Auto-Submit: Ian Lance Taylor Reviewed-by: Michael Knyszek Commit-Queue: Ian Lance Taylor Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/net/netip/export_test.go | 4 ++++ src/net/netip/netip.go | 10 +++++----- src/net/netip/netip_test.go | 8 ++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/net/netip/export_test.go b/src/net/netip/export_test.go index 4febcad893..b2fae1aa47 100644 --- a/src/net/netip/export_test.go +++ b/src/net/netip/export_test.go @@ -16,6 +16,10 @@ type Uint128 = uint128 type AddrDetail = addrDetail +func MakeAddrDetail(isV6 bool, zoneV6 string) AddrDetail { + return AddrDetail{isV6: isV6, zoneV6: zoneV6} +} + func Mk128(hi, lo uint64) Uint128 { return uint128{hi, lo} } diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 57063eeb71..a1e93cb29b 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -59,8 +59,8 @@ type Addr struct { // addrDetail represents the details of an Addr, like address family and IPv6 zone. type addrDetail struct { - IsV6 bool // IPv4 is false, IPv6 is true. - ZoneV6 string // != "" only if IsV6 is true. + isV6 bool // IPv4 is false, IPv6 is true. + zoneV6 string // != "" only if IsV6 is true. } // z0, z4, and z6noz are sentinel Addr.z values. @@ -68,7 +68,7 @@ type addrDetail struct { var ( z0 unique.Handle[addrDetail] z4 = unique.Make(addrDetail{}) - z6noz = unique.Make(addrDetail{IsV6: true}) + z6noz = unique.Make(addrDetail{isV6: true}) ) // IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast @@ -410,7 +410,7 @@ func (ip Addr) Zone() string { if ip.z == z0 { return "" } - return ip.z.Value().ZoneV6 + return ip.z.Value().zoneV6 } // Compare returns an integer comparing two IPs. @@ -495,7 +495,7 @@ func (ip Addr) WithZone(zone string) Addr { ip.z = z6noz return ip } - ip.z = unique.Make(addrDetail{IsV6: true, ZoneV6: zone}) + ip.z = unique.Make(addrDetail{isV6: true, zoneV6: zone}) return ip } diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index ad0e754208..94c70f2290 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -112,18 +112,18 @@ func TestParseAddr(t *testing.T) { // IPv6 with a zone specifier. { in: "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0", - ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth0"})), + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), unique.Make(MakeAddrDetail(true, "eth0"))), }, // IPv6 with dotted decimal and zone specifier. { in: "1:2::ffff:192.168.140.255%eth1", - ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth1"})), + ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), unique.Make(MakeAddrDetail(true, "eth1"))), str: "1:2::ffff:c0a8:8cff%eth1", }, // 4-in-6 with zone { in: "::ffff:192.168.140.255%eth1", - ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth1"})), + ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), unique.Make(MakeAddrDetail(true, "eth1"))), str: "::ffff:192.168.140.255%eth1", }, // IPv6 with capital letters. @@ -1723,7 +1723,7 @@ var parseBenchInputs = []struct { } func BenchmarkParseAddr(b *testing.B) { - sinkInternValue = unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth1"}) // Pin to not benchmark the intern package + sinkInternValue = unique.Make(MakeAddrDetail(true, "eth1")) // Pin to not benchmark the intern package for _, test := range parseBenchInputs { b.Run(test.name, func(b *testing.B) { b.ReportAllocs() From 085cf0fcdc4faa2f473839f8cc1860ec5bcf97a3 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 24 Jun 2024 07:57:45 -0700 Subject: [PATCH 20/72] net/netip: add test that Compare and reflect.DeepEqual match Updates #68113 Change-Id: I1107686ef364f77f48f55534ea8ec68d1785e1e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/594375 Auto-Submit: Brad Fitzpatrick LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Michael Knyszek --- src/net/netip/netip_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 94c70f2290..e1a0a83f64 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -893,6 +893,15 @@ func TestAddrLessCompare(t *testing.T) { {mustIP("::1%a"), mustIP("::1%b"), true}, {mustIP("::1%a"), mustIP("::1%a"), false}, {mustIP("::1%b"), mustIP("::1%a"), false}, + + // For Issue 68113, verify that an IPv4 address and a + // v4-mapped-IPv6 address differing only in their zone + // pointer are unequal via all three of + // ==/Compare/reflect.DeepEqual. In Go 1.22 and + // earlier, these were accidentally equal via + // DeepEqual due to their zone pointers (z) differing + // but pointing to identical structures. + {mustIP("::ffff:11.1.1.12"), mustIP("11.1.1.12"), false}, } for _, tt := range tests { got := tt.a.Less(tt.b) @@ -920,6 +929,12 @@ func TestAddrLessCompare(t *testing.T) { t.Errorf("Less(%q, %q) was correctly %v, but so was Less(%q, %q)", tt.a, tt.b, got, tt.b, tt.a) } } + + // Also check reflect.DeepEqual. See issue 68113. + deepEq := reflect.DeepEqual(tt.a, tt.b) + if (cmp == 0) != deepEq { + t.Errorf("%q and %q differ in == (%v) vs reflect.DeepEqual (%v)", tt.a, tt.b, cmp == 0, deepEq) + } } // And just sort. From 0def9d5c02166b50a011b4cc8d4c1d891a04f89d Mon Sep 17 00:00:00 2001 From: Sebastian Nickolls Date: Thu, 25 Apr 2024 17:19:20 +0100 Subject: [PATCH 21/72] cmd/internal/obj/arm64: Enable arm64 assembler tests for cross-compiler builds Some of the tests for the arm64 assembler are not running for cross-compiled arm64 builds with GOARCH=arm64. This patch allows the tests to run for all architectures and moves the test that can only run on arm64 into its own conditionally compiled file. Updates #44734 Change-Id: I045870d47cdc1280bfacc1ef275f34504278ed89 Reviewed-on: https://go-review.googlesource.com/c/go/+/587315 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Sebastian Nickolls --- src/cmd/internal/obj/arm64/asm_arm64_test.go | 297 +------------------ src/cmd/internal/obj/arm64/asm_test.go | 258 ++++++++++++++++ 2 files changed, 259 insertions(+), 296 deletions(-) create mode 100644 src/cmd/internal/obj/arm64/asm_test.go diff --git a/src/cmd/internal/obj/arm64/asm_arm64_test.go b/src/cmd/internal/obj/arm64/asm_arm64_test.go index 068039496a..83d137a084 100644 --- a/src/cmd/internal/obj/arm64/asm_arm64_test.go +++ b/src/cmd/internal/obj/arm64/asm_arm64_test.go @@ -4,302 +4,7 @@ package arm64 -import ( - "bytes" - "fmt" - "internal/testenv" - "os" - "path/filepath" - "regexp" - "testing" -) - -func TestSplitImm24uScaled(t *testing.T) { - tests := []struct { - v int32 - shift int - wantErr bool - wantHi int32 - wantLo int32 - }{ - { - v: 0, - shift: 0, - wantHi: 0, - wantLo: 0, - }, - { - v: 0x1001, - shift: 0, - wantHi: 0x1000, - wantLo: 0x1, - }, - { - v: 0xffffff, - shift: 0, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0xffffff, - shift: 1, - wantErr: true, - }, - { - v: 0xfe, - shift: 1, - wantHi: 0x0, - wantLo: 0x7f, - }, - { - v: 0x10fe, - shift: 1, - wantHi: 0x0, - wantLo: 0x87f, - }, - { - v: 0x2002, - shift: 1, - wantHi: 0x2000, - wantLo: 0x1, - }, - { - v: 0xfffffe, - shift: 1, - wantHi: 0xffe000, - wantLo: 0xfff, - }, - { - v: 0x1000ffe, - shift: 1, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0x1001000, - shift: 1, - wantErr: true, - }, - { - v: 0xfffffe, - shift: 2, - wantErr: true, - }, - { - v: 0x4004, - shift: 2, - wantHi: 0x4000, - wantLo: 0x1, - }, - { - v: 0xfffffc, - shift: 2, - wantHi: 0xffc000, - wantLo: 0xfff, - }, - { - v: 0x1002ffc, - shift: 2, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0x1003000, - shift: 2, - wantErr: true, - }, - { - v: 0xfffffe, - shift: 3, - wantErr: true, - }, - { - v: 0x8008, - shift: 3, - wantHi: 0x8000, - wantLo: 0x1, - }, - { - v: 0xfffff8, - shift: 3, - wantHi: 0xff8000, - wantLo: 0xfff, - }, - { - v: 0x1006ff8, - shift: 3, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0x1007000, - shift: 3, - wantErr: true, - }, - } - for _, test := range tests { - hi, lo, err := splitImm24uScaled(test.v, test.shift) - switch { - case err == nil && test.wantErr: - t.Errorf("splitImm24uScaled(%v, %v) succeeded, want error", test.v, test.shift) - case err != nil && !test.wantErr: - t.Errorf("splitImm24uScaled(%v, %v) failed: %v", test.v, test.shift, err) - case !test.wantErr: - if got, want := hi, test.wantHi; got != want { - t.Errorf("splitImm24uScaled(%x, %x) - got hi %x, want %x", test.v, test.shift, got, want) - } - if got, want := lo, test.wantLo; got != want { - t.Errorf("splitImm24uScaled(%x, %x) - got lo %x, want %x", test.v, test.shift, got, want) - } - } - } - for shift := 0; shift <= 3; shift++ { - for v := int32(0); v < 0xfff000+0xfff< Date: Fri, 21 Jun 2024 16:59:21 -0700 Subject: [PATCH 22/72] os: TestChtimes: separate hasNoatime Move the noatime check to a separate function (to be used by CL 91535), adding some documentation along the way. Unify the atime error message. Change-Id: I5f75a4399f6e1b16ae20438003de5460f3eeb5aa Reviewed-on: https://go-review.googlesource.com/c/go/+/594075 Reviewed-by: Ian Lance Taylor Reviewed-by: Joedian Reid LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor --- src/os/os_test.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index 2a6b1bf9f5..b3fbe42ba7 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1361,6 +1361,17 @@ func TestTruncateNonexistentFile(t *testing.T) { assertPathError(t, path, err) } +var hasNoatime = sync.OnceValue(func() bool { + // A sloppy way to check if noatime flag is set (as all filesystems are + // checked, not just the one we're interested in). A correct way + // would be to use statvfs syscall and check if flags has ST_NOATIME, + // but the syscall is OS-specific and is not even wired into Go stdlib. + // + // Only used on NetBSD (which ignores explicit atime updates with noatime). + mounts, _ := ReadFile("/proc/mounts") + return bytes.Contains(mounts, []byte("noatime")) +}) + func TestChtimes(t *testing.T) { t.Parallel() @@ -1523,6 +1534,7 @@ func testChtimes(t *testing.T, name string) { pat := Atime(postStat) pmt := postStat.ModTime() if !pat.Before(at) { + errormsg := fmt.Sprintf("AccessTime didn't go backwards; was=%v, after=%v", at, pat) switch runtime.GOOS { case "plan9": // Mtime is the time of the last change of @@ -1530,14 +1542,14 @@ func testChtimes(t *testing.T, name string) { // the contents are accessed; also, it is set // whenever mtime is set. case "netbsd": - mounts, _ := ReadFile("/proc/mounts") - if strings.Contains(string(mounts), "noatime") { - t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.") + if hasNoatime() { + t.Log(errormsg) + t.Log("Known NetBSD issue (atime not changed on fs mounted with noatime); ignoring.") } else { - t.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at, pat) + t.Errorf(errormsg) } default: - t.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at, pat) + t.Errorf(errormsg) } } From cf54a3d11469e3e9bd531ee2cdeaf613467923f1 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sun, 23 Jun 2024 14:10:14 +0200 Subject: [PATCH 23/72] crypto/tls: replay test recordings without network There is no reason to go across a pipe when replaying a conn recording. This avoids the complexity of using localPipe and goroutines, and makes handshake benchmarks more accurate, as we don't measure network overhead. Also note how it removes the need for -fast: operating locally we know when the flow is over and can error out immediately, without waiting for a read from the feeder on the other side of the pipe to timeout. Avoids some noise in #67979, but doesn't fix the two root causes: localPipe flakes and testing.B races. Updates #67979 Change-Id: I153d3fa5a24847f3947823e8c3a7bc639f89bc1d Reviewed-on: https://go-review.googlesource.com/c/go/+/594255 Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker Reviewed-by: Joedian Reid --- src/crypto/tls/handshake_client_test.go | 276 ++++++++++-------------- src/crypto/tls/handshake_server_test.go | 95 ++------ src/crypto/tls/handshake_test.go | 72 ++++++- 3 files changed, 210 insertions(+), 233 deletions(-) diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 4570f5b05e..501f9c6755 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -283,7 +283,7 @@ func (test *clientTest) loadData() (flows [][]byte, err error) { } func (test *clientTest) run(t *testing.T, write bool) { - var clientConn, serverConn net.Conn + var clientConn net.Conn var recordingConn *recordingConn var childProcess *exec.Cmd var stdin opensslInput @@ -302,178 +302,138 @@ func (test *clientTest) run(t *testing.T, write bool) { } }() } else { - clientConn, serverConn = localPipe(t) + flows, err := test.loadData() + if err != nil { + t.Fatalf("failed to load data from %s: %v", test.dataPath(), err) + } + clientConn = &replayingConn{t: t, flows: flows, reading: false} } - doneChan := make(chan bool) - defer func() { - clientConn.Close() - <-doneChan - }() - go func() { - defer close(doneChan) + config := test.config + if config == nil { + config = testConfig + } + client := Client(clientConn, config) + defer client.Close() - config := test.config - if config == nil { - config = testConfig + if _, err := client.Write([]byte("hello\n")); err != nil { + t.Errorf("Client.Write failed: %s", err) + return + } + + for i := 1; i <= test.numRenegotiations; i++ { + // The initial handshake will generate a + // handshakeComplete signal which needs to be quashed. + if i == 1 && write { + <-stdout.handshakeComplete } - client := Client(clientConn, config) - defer client.Close() - if _, err := client.Write([]byte("hello\n")); err != nil { + // OpenSSL will try to interleave application data and + // a renegotiation if we send both concurrently. + // Therefore: ask OpensSSL to start a renegotiation, run + // a goroutine to call client.Read and thus process the + // renegotiation request, watch for OpenSSL's stdout to + // indicate that the handshake is complete and, + // finally, have OpenSSL write something to cause + // client.Read to complete. + if write { + stdin <- opensslRenegotiate + } + + signalChan := make(chan struct{}) + + go func() { + defer close(signalChan) + + buf := make([]byte, 256) + n, err := client.Read(buf) + + if test.checkRenegotiationError != nil { + newErr := test.checkRenegotiationError(i, err) + if err != nil && newErr == nil { + return + } + err = newErr + } + + if err != nil { + t.Errorf("Client.Read failed after renegotiation #%d: %s", i, err) + return + } + + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) + } + + if expected := i + 1; client.handshakes != expected { + t.Errorf("client should have recorded %d handshakes, but believes that %d have occurred", expected, client.handshakes) + } + }() + + if write && test.renegotiationExpectedToFail != i { + <-stdout.handshakeComplete + stdin <- opensslSendSentinel + } + <-signalChan + } + + if test.sendKeyUpdate { + if write { + <-stdout.handshakeComplete + stdin <- opensslKeyUpdate + } + + doneRead := make(chan struct{}) + + go func() { + defer close(doneRead) + + buf := make([]byte, 256) + n, err := client.Read(buf) + + if err != nil { + t.Errorf("Client.Read failed after KeyUpdate: %s", err) + return + } + + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) + } + }() + + if write { + // There's no real reason to wait for the client KeyUpdate to + // send data with the new server keys, except that s_server + // drops writes if they are sent at the wrong time. + <-stdout.readKeyUpdate + stdin <- opensslSendSentinel + } + <-doneRead + + if _, err := client.Write([]byte("hello again\n")); err != nil { t.Errorf("Client.Write failed: %s", err) return } + } - for i := 1; i <= test.numRenegotiations; i++ { - // The initial handshake will generate a - // handshakeComplete signal which needs to be quashed. - if i == 1 && write { - <-stdout.handshakeComplete - } - - // OpenSSL will try to interleave application data and - // a renegotiation if we send both concurrently. - // Therefore: ask OpensSSL to start a renegotiation, run - // a goroutine to call client.Read and thus process the - // renegotiation request, watch for OpenSSL's stdout to - // indicate that the handshake is complete and, - // finally, have OpenSSL write something to cause - // client.Read to complete. - if write { - stdin <- opensslRenegotiate - } - - signalChan := make(chan struct{}) - - go func() { - defer close(signalChan) - - buf := make([]byte, 256) - n, err := client.Read(buf) - - if test.checkRenegotiationError != nil { - newErr := test.checkRenegotiationError(i, err) - if err != nil && newErr == nil { - return - } - err = newErr - } - - if err != nil { - t.Errorf("Client.Read failed after renegotiation #%d: %s", i, err) - return - } - - buf = buf[:n] - if !bytes.Equal([]byte(opensslSentinel), buf) { - t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) - } - - if expected := i + 1; client.handshakes != expected { - t.Errorf("client should have recorded %d handshakes, but believes that %d have occurred", expected, client.handshakes) - } - }() - - if write && test.renegotiationExpectedToFail != i { - <-stdout.handshakeComplete - stdin <- opensslSendSentinel - } - <-signalChan - } - - if test.sendKeyUpdate { - if write { - <-stdout.handshakeComplete - stdin <- opensslKeyUpdate - } - - doneRead := make(chan struct{}) - - go func() { - defer close(doneRead) - - buf := make([]byte, 256) - n, err := client.Read(buf) - - if err != nil { - t.Errorf("Client.Read failed after KeyUpdate: %s", err) - return - } - - buf = buf[:n] - if !bytes.Equal([]byte(opensslSentinel), buf) { - t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) - } - }() - - if write { - // There's no real reason to wait for the client KeyUpdate to - // send data with the new server keys, except that s_server - // drops writes if they are sent at the wrong time. - <-stdout.readKeyUpdate - stdin <- opensslSendSentinel - } - <-doneRead - - if _, err := client.Write([]byte("hello again\n")); err != nil { - t.Errorf("Client.Write failed: %s", err) - return - } - } - - if test.validate != nil { - if err := test.validate(client.ConnectionState()); err != nil { - t.Errorf("validate callback returned error: %s", err) - } - } - - // If the server sent us an alert after our last flight, give it a - // chance to arrive. - if write && test.renegotiationExpectedToFail == 0 { - if err := peekError(client); err != nil { - t.Errorf("final Read returned an error: %s", err) - } - } - }() - - if !write { - flows, err := test.loadData() - if err != nil { - t.Fatalf("%s: failed to load data from %s: %v", test.name, test.dataPath(), err) - } - for i, b := range flows { - if i%2 == 1 { - if *fast { - serverConn.SetWriteDeadline(time.Now().Add(1 * time.Second)) - } else { - serverConn.SetWriteDeadline(time.Now().Add(1 * time.Minute)) - } - serverConn.Write(b) - continue - } - bb := make([]byte, len(b)) - if *fast { - serverConn.SetReadDeadline(time.Now().Add(1 * time.Second)) - } else { - serverConn.SetReadDeadline(time.Now().Add(1 * time.Minute)) - } - _, err := io.ReadFull(serverConn, bb) - if err != nil { - t.Fatalf("%s, flow %d: %s", test.name, i+1, err) - } - if !bytes.Equal(b, bb) { - t.Fatalf("%s, flow %d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) - } + if test.validate != nil { + if err := test.validate(client.ConnectionState()); err != nil { + t.Errorf("validate callback returned error: %s", err) } } - <-doneChan - if !write { - serverConn.Close() + // If the server sent us an alert after our last flight, give it a + // chance to arrive. + if write && test.renegotiationExpectedToFail == 0 { + if err := peekError(client); err != nil { + t.Errorf("final Read returned an error: %s", err) + } } if write { + clientConn.Close() path := test.dataPath() out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 44bc8f1bb7..94d3d0f6dc 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -21,6 +21,7 @@ import ( "os/exec" "path/filepath" "runtime" + "slices" "strings" "testing" "time" @@ -659,7 +660,7 @@ func (test *serverTest) loadData() (flows [][]byte, err error) { } func (test *serverTest) run(t *testing.T, write bool) { - var clientConn, serverConn net.Conn + var serverConn net.Conn var recordingConn *recordingConn var childProcess *exec.Cmd @@ -676,65 +677,33 @@ func (test *serverTest) run(t *testing.T, write bool) { } }() } else { - clientConn, serverConn = localPipe(t) + flows, err := test.loadData() + if err != nil { + t.Fatalf("Failed to load data from %s", test.dataPath()) + } + serverConn = &replayingConn{t: t, flows: flows, reading: true} } config := test.config if config == nil { config = testConfig } server := Server(serverConn, config) - connStateChan := make(chan ConnectionState, 1) - go func() { - _, err := server.Write([]byte("hello, world\n")) - if len(test.expectHandshakeErrorIncluding) > 0 { - if err == nil { - t.Errorf("Error expected, but no error returned") - } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { - t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) - } - } else { - if err != nil { - t.Logf("Error from Server.Write: '%s'", err) - } - } - server.Close() - serverConn.Close() - connStateChan <- server.ConnectionState() - }() - if !write { - flows, err := test.loadData() + _, err := server.Write([]byte("hello, world\n")) + if len(test.expectHandshakeErrorIncluding) > 0 { + if err == nil { + t.Errorf("Error expected, but no error returned") + } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { + t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) + } + } else { if err != nil { - t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath()) + t.Logf("Error from Server.Write: '%s'", err) } - for i, b := range flows { - if i%2 == 0 { - if *fast { - clientConn.SetWriteDeadline(time.Now().Add(1 * time.Second)) - } else { - clientConn.SetWriteDeadline(time.Now().Add(1 * time.Minute)) - } - clientConn.Write(b) - continue - } - bb := make([]byte, len(b)) - if *fast { - clientConn.SetReadDeadline(time.Now().Add(1 * time.Second)) - } else { - clientConn.SetReadDeadline(time.Now().Add(1 * time.Minute)) - } - n, err := io.ReadFull(clientConn, bb) - if err != nil { - t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b) - } - if !bytes.Equal(b, bb) { - t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) - } - } - clientConn.Close() } + server.Close() - connState := <-connStateChan + connState := server.ConnectionState() peerCerts := connState.PeerCertificates if len(peerCerts) == len(test.expectedPeerCerts) { for i, peerCert := range peerCerts { @@ -754,6 +723,7 @@ func (test *serverTest) run(t *testing.T, write bool) { } if write { + serverConn.Close() path := test.dataPath() out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { @@ -1330,37 +1300,14 @@ func benchmarkHandshakeServer(b *testing.B, version uint16, cipherSuite uint16, serverConn.Close() flows := serverConn.(*recordingConn).flows - feeder := make(chan struct{}) - clientConn, serverConn = localPipe(b) - - go func() { - for range feeder { - for i, f := range flows { - if i%2 == 0 { - clientConn.Write(f) - continue - } - ff := make([]byte, len(f)) - n, err := io.ReadFull(clientConn, ff) - if err != nil { - b.Errorf("#%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", i+1, err, n, len(ff), ff[:n], f) - } - if !bytes.Equal(f, ff) { - b.Errorf("#%d: mismatch on read: got:%x want:%x", i+1, ff, f) - } - } - } - }() - b.ResetTimer() for i := 0; i < b.N; i++ { - feeder <- struct{}{} - server := Server(serverConn, config) + replay := &replayingConn{t: b, flows: slices.Clone(flows), reading: true} + server := Server(replay, config) if err := server.Handshake(); err != nil { b.Fatalf("handshake failed: %v", err) } } - close(feeder) } func BenchmarkHandshakeServer(b *testing.B) { diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go index 57fc761dbb..bc3d23d5ad 100644 --- a/src/crypto/tls/handshake_test.go +++ b/src/crypto/tls/handshake_test.go @@ -6,6 +6,7 @@ package tls import ( "bufio" + "bytes" "crypto/ed25519" "crypto/x509" "encoding/hex" @@ -42,7 +43,6 @@ import ( var ( update = flag.Bool("update", false, "update golden files on failure") - fast = flag.Bool("fast", false, "impose a quick, possibly flaky timeout on recorded tests") keyFile = flag.String("keylog", "", "destination file for KeyLogWriter") bogoMode = flag.Bool("bogo-mode", false, "Enabled bogo shim mode, ignore everything else") bogoFilter = flag.String("bogo-filter", "", "BoGo test filter") @@ -223,6 +223,76 @@ func parseTestData(r io.Reader) (flows [][]byte, err error) { return flows, nil } +// replayingConn is a net.Conn that replays flows recorded by recordingConn. +type replayingConn struct { + t testing.TB + sync.Mutex + flows [][]byte + reading bool +} + +var _ net.Conn = (*replayingConn)(nil) + +func (r *replayingConn) Read(b []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + + if !r.reading { + r.t.Errorf("expected write, got read") + return 0, fmt.Errorf("recording expected write, got read") + } + + n = copy(b, r.flows[0]) + r.flows[0] = r.flows[0][n:] + if len(r.flows[0]) == 0 { + r.flows = r.flows[1:] + if len(r.flows) == 0 { + return n, io.EOF + } else { + r.reading = false + } + } + return n, nil +} + +func (r *replayingConn) Write(b []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + + if r.reading { + r.t.Errorf("expected read, got write") + return 0, fmt.Errorf("recording expected read, got write") + } + + if !bytes.HasPrefix(r.flows[0], b) { + r.t.Errorf("write mismatch: expected %x, got %x", r.flows[0], b) + return 0, fmt.Errorf("write mismatch") + } + r.flows[0] = r.flows[0][len(b):] + if len(r.flows[0]) == 0 { + r.flows = r.flows[1:] + r.reading = true + } + return len(b), nil +} + +func (r *replayingConn) Close() error { + r.Lock() + defer r.Unlock() + + if len(r.flows) > 0 { + r.t.Errorf("closed with unfinished flows") + return fmt.Errorf("unexpected close") + } + return nil +} + +func (r *replayingConn) LocalAddr() net.Addr { return nil } +func (r *replayingConn) RemoteAddr() net.Addr { return nil } +func (r *replayingConn) SetDeadline(t time.Time) error { return nil } +func (r *replayingConn) SetReadDeadline(t time.Time) error { return nil } +func (r *replayingConn) SetWriteDeadline(t time.Time) error { return nil } + // tempFile creates a temp file containing contents and returns its path. func tempFile(contents string) string { file, err := os.CreateTemp("", "go-tls-test") From 29b1a6765fb5f124171d94f157b6d6c3b2687468 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 17 Jun 2024 14:54:22 -0700 Subject: [PATCH 24/72] net/http: document that Request.Clone does not deep copy Body Fixes #36095 Change-Id: I94ae014b0ee45b4aeb38cb247e42cfc13f663ded Reviewed-on: https://go-review.googlesource.com/c/go/+/593175 LUCI-TryBot-Result: Go LUCI Reviewed-by: Jonathan Amsterdam --- src/net/http/request.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/http/request.go b/src/net/http/request.go index 456615a79a..ad1b5a620b 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -377,6 +377,8 @@ func (r *Request) WithContext(ctx context.Context) *Request { // Clone returns a deep copy of r with its context changed to ctx. // The provided ctx must be non-nil. // +// Clone only makes a shallow copy of the Body field. +// // For an outgoing client request, the context controls the entire // lifetime of a request and its response: obtaining a connection, // sending the request, and reading the response headers and body. From f214a760754ac0584999fb8098ce6172181ed791 Mon Sep 17 00:00:00 2001 From: "Hana (Hyang-Ah) Kim" Date: Mon, 24 Jun 2024 11:45:12 -0400 Subject: [PATCH 25/72] cmd/vendor: vendor x/telemetry@38a4430 For #68109 Change-Id: I73a3d23dd6c15ff4954ebe7a52c6c308fea947ae Reviewed-on: https://go-review.googlesource.com/c/go/+/593684 Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI Auto-Submit: Hyang-Ah Hana Kim --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 2 ++ .../x/telemetry/internal/telemetry/proginfo.go | 11 +++++++---- src/cmd/vendor/modules.txt | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 0a17a414b5..3058165dbf 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -9,7 +9,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c + golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 49849d10b4..4449bb0b2c 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,6 +18,8 @@ golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c h1:zNxtD9mZQCgRwCNanVRlJ/XlOyATHcbR+09LzoArRl4= golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 h1:fzUVo05u80jHc31RGqQsPYEAGMXS8tyK5azYUK2sSms= +golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go b/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go index 20be9664fc..60cb0edc79 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go @@ -9,8 +9,6 @@ import ( "path/filepath" "runtime/debug" "strings" - - "golang.org/x/mod/module" ) // IsToolchainProgram reports whether a program with the given path is a Go @@ -43,8 +41,13 @@ func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) { progVers = goVers } else { progVers = info.Main.Version - if strings.Contains(progVers, "devel") || module.IsPseudoVersion(progVers) { - // We don't want to track pseudo versions, but may want to track prereleases. + if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 { + // Heuristically mark all pseudo-version-like version strings as "devel" + // to avoid creating too many counter files. + // We should not use regexp that pulls in large dependencies. + // Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions). + // This heuristic still allows use to track prerelease + // versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1). progVers = "devel" } } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 5184adb1f2..f4eefe4a1d 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -45,7 +45,7 @@ golang.org/x/sync/semaphore golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c +# golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter From 68315bc8ce8c7fd1a9e47e73b2d18ef21f8c6d9a Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Mon, 24 Jun 2024 16:39:21 -0400 Subject: [PATCH 26/72] cmd: run go mod tidy after CL 593684 Reported by TestAllDependencies/cmd(thorough) in cmd/internal/moddeps. Change-Id: I897baf00efbfebd07abe387f54c7ce4fc14444e6 Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/594536 Auto-Submit: Dmitri Shuralyov Reviewed-by: Hyang-Ah Hana Kim Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI --- src/cmd/go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 4449bb0b2c..081ced64dc 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,8 +16,6 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c h1:zNxtD9mZQCgRwCNanVRlJ/XlOyATHcbR+09LzoArRl4= -golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 h1:fzUVo05u80jHc31RGqQsPYEAGMXS8tyK5azYUK2sSms= golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= From b3b4556c245c8f21872910ee866133428bbb5a60 Mon Sep 17 00:00:00 2001 From: func25 Date: Sun, 23 Jun 2024 05:53:47 +0000 Subject: [PATCH 27/72] cmd/compile: update README to reflect dead code elimination changes The description of middle-end dead code elimination is inconsistent with the current implementation. The early dead code elimination pass of IR nodes is no longer located in cmd/compile/internal/deadcode and is no longer called by gc/main.go:Main. It has been moved to the unified IR writer phase. This update modifies the README to reflect this architectural change. Change-Id: I78bd486edefd6b02948fee7de9ce6c83b147bc1d GitHub-Last-Rev: 76493ce8b08cd585d761d65d29b984360f7ee628 GitHub-Pull-Request: golang/go#68134 Reviewed-on: https://go-review.googlesource.com/c/go/+/593638 Reviewed-by: Robert Griesemer Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Auto-Submit: Keith Randall --- src/cmd/compile/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/README.md b/src/cmd/compile/README.md index 3fc7ca6ec6..cffb4e7a80 100644 --- a/src/cmd/compile/README.md +++ b/src/cmd/compile/README.md @@ -63,7 +63,6 @@ Unified IR is also involved in import/export of packages and inlining. ### 4. Middle end -* `cmd/compile/internal/deadcode` (dead code elimination) * `cmd/compile/internal/inline` (function call inlining) * `cmd/compile/internal/devirtualize` (devirtualization of known interface method calls) * `cmd/compile/internal/escape` (escape analysis) @@ -72,6 +71,8 @@ Several optimization passes are performed on the IR representation: dead code elimination, (early) devirtualization, function call inlining, and escape analysis. +The early dead code elimination pass is integrated into the unified IR writer phase. + ### 5. Walk * `cmd/compile/internal/walk` (order of evaluation, desugaring) From b1fd047508aad9f5038dc04d78146cc582328bf5 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 15 Jun 2024 01:28:46 +1000 Subject: [PATCH 28/72] cmd/internal/obj/arm64: fix return with register ARM64 allows for a register to be specified with a return instruction. While the assembler parsing and encoding currently supports this, the preprocess function uses LR unconditionally. Correct this such that if a register is specified, the register is used. Change-Id: I708f6c7e910d141559b60d2d5ee76ae2e1dc3a0e Reviewed-on: https://go-review.googlesource.com/c/go/+/592796 Reviewed-by: Cherry Mui Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/cmd/asm/internal/asm/testdata/arm64.s | 6 +++++- src/cmd/internal/obj/arm64/obj7.go | 12 +++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index ecad08b37a..f12cdaf921 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -961,7 +961,11 @@ again: CASPD (R2, R3), (R2), (R8, R9) // 487c2248 // RET - RET + RET // c0035fd6 + RET R0 // 00005fd6 + RET R6 // c0005fd6 + RET R27 // 60035fd6 + RET R30 // c0035fd6 RET foo(SB) // B/BL/B.cond cases, and canonical names JMP, CALL. diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 0ab5939b84..20498bc2c6 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -552,7 +552,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var q *obj.Prog var q1 *obj.Prog - var retjmp *obj.LSym for p := c.cursym.Func().Text; p != nil; p = p.Link { o := p.As switch o { @@ -846,7 +845,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { break } - retjmp = p.To.Sym + retJMP, retReg := p.To.Sym, p.To.Reg + if retReg == 0 { + retReg = REGLINK + } p.To = obj.Addr{} if c.cursym.Func().Text.Mark&LEAF != 0 { if c.autosize != 0 { @@ -924,10 +926,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p = q } - if retjmp != nil { // retjmp + if retJMP != nil { p.As = AB p.To.Type = obj.TYPE_BRANCH - p.To.Sym = retjmp + p.To.Sym = retJMP p.Spadj = +c.autosize break } @@ -935,7 +937,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p.As = obj.ARET p.To.Type = obj.TYPE_MEM p.To.Offset = 0 - p.To.Reg = REGLINK + p.To.Reg = retReg p.Spadj = +c.autosize case AADD, ASUB: From 90bcc552c0347948166817a602f612f219bc980c Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 24 Jun 2024 10:01:47 -0700 Subject: [PATCH 29/72] crypto/tls: apply QUIC session event flag to QUICResumeSession events Go 1.23 adds two new events to QUICConns: QUICStoreSessionEvent and QUICResumeSessionEvent. We added a QUICConfig.EnableStoreSessionEvent flag to control whether the store-session event is provided or not, because receiving this event requires additional action from the caller: the session must be explicitly stored with QUICConn.StoreSession. We did not add a control for whether the resume-session event is provided, because this event requires no action and the caller is expected to ignore unknown events. However, we never documented the expectation that callers ignore unknown events, and quic-go produces an error when receiving an unexpected event. So change the EnableStoreSessionEvent flag to apply to both new events. Fixes #68124 For #63691 Change-Id: I84af487e52b3815f7b648e09884608f8915cd645 Reviewed-on: https://go-review.googlesource.com/c/go/+/594475 Reviewed-by: Marten Seemann LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker --- api/go1.23.txt | 2 +- src/crypto/tls/handshake_client.go | 4 +- src/crypto/tls/handshake_client_tls13.go | 2 +- src/crypto/tls/handshake_server_tls13.go | 2 +- src/crypto/tls/quic.go | 16 +-- src/crypto/tls/quic_test.go | 156 ++++++++++++----------- 6 files changed, 99 insertions(+), 83 deletions(-) diff --git a/api/go1.23.txt b/api/go1.23.txt index dc92d3fe56..9363bd41f3 100644 --- a/api/go1.23.txt +++ b/api/go1.23.txt @@ -18,7 +18,7 @@ pkg crypto/tls, type Config struct, EncryptedClientHelloRejectionVerify func(Con pkg crypto/tls, type ConnectionState struct, ECHAccepted bool #63369 pkg crypto/tls, type ECHRejectionError struct #63369 pkg crypto/tls, type ECHRejectionError struct, RetryConfigList []uint8 #63369 -pkg crypto/tls, type QUICConfig struct, EnableStoreSessionEvent bool #63691 +pkg crypto/tls, type QUICConfig struct, EnableSessionEvents bool #63691 pkg crypto/tls, type QUICEvent struct, SessionState *SessionState #63691 pkg crypto/tls, type QUICSessionTicketOptions struct, Extra [][]uint8 #63691 pkg crypto/x509, func ParseOID(string) (OID, error) #66249 diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 553d2dde01..5025657590 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -478,7 +478,9 @@ func (c *Conn) loadSession(hello *clientHelloMsg) ( } if c.quic != nil { - c.quicResumeSession(session) + if c.quic.enableSessionEvents { + c.quicResumeSession(session) + } // For 0-RTT, the cipher suite has to match exactly, and we need to be // offering the same ALPN. diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 6744e713c9..db5e35d9a4 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -900,7 +900,7 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { session.ageAdd = msg.ageAdd session.EarlyData = c.quic != nil && msg.maxEarlyData == 0xffffffff // RFC 9001, Section 4.6.1 session.ticket = msg.label - if c.quic != nil && c.quic.enableStoreSessionEvent { + if c.quic != nil && c.quic.enableSessionEvents { c.quicStoreSession(session) return nil } diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index f24c2671ac..503a732e05 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -377,7 +377,7 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { continue } - if c.quic != nil { + if c.quic != nil && c.quic.enableSessionEvents { if err := c.quicResumeSession(sessionState); err != nil { return err } diff --git a/src/crypto/tls/quic.go b/src/crypto/tls/quic.go index 8e722c6a59..9dd6168b62 100644 --- a/src/crypto/tls/quic.go +++ b/src/crypto/tls/quic.go @@ -50,12 +50,12 @@ type QUICConn struct { type QUICConfig struct { TLSConfig *Config - // EnableStoreSessionEvent may be set to true to enable the - // [QUICStoreSession] event for client connections. + // EnableSessionEvents may be set to true to enable the + // [QUICStoreSession] and [QUICResumeSession] events for client connections. // When this event is enabled, sessions are not automatically // stored in the client session cache. // The application should use [QUICConn.StoreSession] to store sessions. - EnableStoreSessionEvent bool + EnableSessionEvents bool } // A QUICEventKind is a type of operation on a QUIC connection. @@ -113,7 +113,7 @@ const ( // QUICStoreSession indicates that the server has provided state permitting // the client to resume the session. // [QUICEvent.SessionState] is set. - // The application should use [QUICConn.Store] session to store the [SessionState]. + // The application should use [QUICConn.StoreSession] session to store the [SessionState]. // The application may modify the [SessionState] before storing it. // This event only occurs on client connections. QUICStoreSession @@ -165,7 +165,7 @@ type quicState struct { transportParams []byte // to send to the peer - enableStoreSessionEvent bool + enableSessionEvents bool } // QUICClient returns a new TLS client side connection using QUICTransport as the @@ -186,9 +186,9 @@ func QUICServer(config *QUICConfig) *QUICConn { func newQUICConn(conn *Conn, config *QUICConfig) *QUICConn { conn.quic = &quicState{ - signalc: make(chan struct{}), - blockedc: make(chan struct{}), - enableStoreSessionEvent: config.EnableStoreSessionEvent, + signalc: make(chan struct{}), + blockedc: make(chan struct{}), + enableSessionEvents: config.EnableSessionEvents, } conn.quic.events = conn.quic.eventArr[:0] return &QUICConn{ diff --git a/src/crypto/tls/quic_test.go b/src/crypto/tls/quic_test.go index 5a6f66e4de..1bb2e55bdd 100644 --- a/src/crypto/tls/quic_test.go +++ b/src/crypto/tls/quic_test.go @@ -24,22 +24,22 @@ type testQUICConn struct { complete bool } -func newTestQUICClient(t *testing.T, config *Config) *testQUICConn { - q := &testQUICConn{t: t} - q.conn = QUICClient(&QUICConfig{ - TLSConfig: config, - }) +func newTestQUICClient(t *testing.T, config *QUICConfig) *testQUICConn { + q := &testQUICConn{ + t: t, + conn: QUICClient(config), + } t.Cleanup(func() { q.conn.Close() }) return q } -func newTestQUICServer(t *testing.T, config *Config) *testQUICConn { - q := &testQUICConn{t: t} - q.conn = QUICServer(&QUICConfig{ - TLSConfig: config, - }) +func newTestQUICServer(t *testing.T, config *QUICConfig) *testQUICConn { + q := &testQUICConn{ + t: t, + conn: QUICServer(config), + } t.Cleanup(func() { q.conn.Close() }) @@ -140,6 +140,11 @@ func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onEvent return err } } + case QUICStoreSession: + if a != cli { + return errors.New("unexpected QUICStoreSession event received by server") + } + a.conn.StoreSession(e.SessionState) case QUICResumeSession: if a.onResumeSession != nil { a.onResumeSession(e.SessionState) @@ -154,8 +159,8 @@ func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onEvent } func TestQUICConnection(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) @@ -196,13 +201,13 @@ func TestQUICConnection(t *testing.T) { } func TestQUICSessionResumption(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -228,13 +233,13 @@ func TestQUICSessionResumption(t *testing.T) { } func TestQUICFragmentaryData(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -260,8 +265,8 @@ func TestQUICFragmentaryData(t *testing.T) { func TestQUICPostHandshakeClientAuthentication(t *testing.T) { // RFC 9001, Section 4.4. - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -288,8 +293,8 @@ func TestQUICPostHandshakeClientAuthentication(t *testing.T) { func TestQUICPostHandshakeKeyUpdate(t *testing.T) { // RFC 9001, Section 6. - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -312,8 +317,8 @@ func TestQUICPostHandshakeKeyUpdate(t *testing.T) { } func TestQUICPostHandshakeMessageTooLarge(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -334,13 +339,13 @@ func TestQUICPostHandshakeMessageTooLarge(t *testing.T) { } func TestQUICHandshakeError(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.InsecureSkipVerify = false - clientConfig.ServerName = "name" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.InsecureSkipVerify = false + clientConfig.TLSConfig.ServerName = "name" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -360,9 +365,9 @@ func TestQUICHandshakeError(t *testing.T) { // and that it reports the application protocol as soon as it has been // negotiated. func TestQUICConnectionState(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 - config.NextProtos = []string{"h3"} + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 + config.TLSConfig.NextProtos = []string{"h3"} cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -391,10 +396,10 @@ func TestQUICStartContextPropagation(t *testing.T) { const key = "key" const value = "value" ctx := context.WithValue(context.Background(), key, value) - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 calls := 0 - config.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) { + config.TLSConfig.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) { calls++ got, _ := info.Context().Value(key).(string) if got != value { @@ -415,13 +420,13 @@ func TestQUICStartContextPropagation(t *testing.T) { } func TestQUICDelayedTransportParameters(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cliParams := "client params" srvParams := "server params" @@ -449,8 +454,8 @@ func TestQUICDelayedTransportParameters(t *testing.T) { } func TestQUICEmptyTransportParameters(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) @@ -475,8 +480,8 @@ func TestQUICEmptyTransportParameters(t *testing.T) { } func TestQUICCanceledWaitingForData(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) cli.conn.Start(context.Background()) @@ -489,8 +494,8 @@ func TestQUICCanceledWaitingForData(t *testing.T) { } func TestQUICCanceledWaitingForTransportParams(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.Start(context.Background()) for cli.conn.NextEvent().Kind != QUICTransportParametersRequired { @@ -502,15 +507,15 @@ func TestQUICCanceledWaitingForTransportParams(t *testing.T) { } func TestQUICEarlyData(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" - clientConfig.NextProtos = []string{"h3"} + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" + clientConfig.TLSConfig.NextProtos = []string{"h3"} - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 - serverConfig.NextProtos = []string{"h3"} + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 + serverConfig.TLSConfig.NextProtos = []string{"h3"} cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -528,7 +533,14 @@ func TestQUICEarlyData(t *testing.T) { cli2.conn.SetTransportParameters(nil) srv2 := newTestQUICServer(t, serverConfig) srv2.conn.SetTransportParameters(nil) - if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil { + onEvent := func(e QUICEvent, src, dst *testQUICConn) bool { + switch e.Kind { + case QUICStoreSession, QUICResumeSession: + t.Errorf("with EnableSessionEvents=false, got unexpected event %v", e.Kind) + } + return false + } + if err := runTestQUICConnection(context.Background(), cli2, srv2, onEvent); err != nil { t.Fatalf("error during second connection handshake: %v", err) } if !cli2.conn.ConnectionState().DidResume { @@ -557,15 +569,17 @@ func TestQUICEarlyDataDeclined(t *testing.T) { } func testQUICEarlyDataDeclined(t *testing.T, server bool) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" - clientConfig.NextProtos = []string{"h3"} + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.EnableSessionEvents = true + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" + clientConfig.TLSConfig.NextProtos = []string{"h3"} - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 - serverConfig.NextProtos = []string{"h3"} + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.EnableSessionEvents = true + serverConfig.TLSConfig.MinVersion = VersionTLS13 + serverConfig.TLSConfig.NextProtos = []string{"h3"} cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) From a2e90be996fb0e75966b1e1097dd20aa07eebc37 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Sun, 9 Jun 2024 12:47:23 -0700 Subject: [PATCH 30/72] os: rewrite TestChtimesWithZeroTimes First, this enables checks on DragonFly BSD, which partially works since CL 589496 (except two things: atime is not supported on hammer2 fs, and when both times are omitted, it doesn't work due to a kernel bug). Second, there are a few problems with TestChtimesWithZeroTimes: - test cases are interdependent (former cases influence the latter ones), making the test using too many different times and also hard to read; - time is changed forward not backward which could be racy; - if the test has failed, it hard to see which exact case is failing. Plus, there are issues with the error exclusion code in TestChtimesWithZeroTimes: - the atime comparison is done twice for the default ("unix") case; - the atime exclusion caused by noatime mount flag applies to all unixes rather than netbsd only as it should; - the atime exclusion tries to read wrong files (/bin/mounts and /etc/mtab instead of /proc/mounts); - the exclusion for netbsd is only applied for 64-bit arches, which seems wrong (and I've reproduced noatime issue on NetBSD 9.4/i386). Let's rewrite it, fixing all these issues, and rename to TestChtimesOmit. NB: TestChtimes can now be removed. Change-Id: If9020256ca920b4db836a1f0b2e055b5fce4a552 Reviewed-on: https://go-review.googlesource.com/c/go/+/591535 Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Joedian Reid LUCI-TryBot-Result: Go LUCI --- src/os/os_test.go | 181 +++++++++++++++++++++------------------------- 1 file changed, 83 insertions(+), 98 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index b3fbe42ba7..9519aa0fc6 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1383,123 +1383,108 @@ func TestChtimes(t *testing.T) { testChtimes(t, f.Name()) } -func TestChtimesWithZeroTimes(t *testing.T) { +func TestChtimesOmit(t *testing.T) { + t.Parallel() + + testChtimesOmit(t, true, false) + testChtimesOmit(t, false, true) + testChtimesOmit(t, true, true) + testChtimesOmit(t, false, false) // Same as TestChtimes. +} + +func testChtimesOmit(t *testing.T, omitAt, omitMt bool) { + t.Logf("omit atime: %v, mtime: %v", omitAt, omitMt) file := newFile(t) _, err := file.Write([]byte("hello, world\n")) if err != nil { - t.Fatalf("Write: %s", err) + t.Fatal(err) } - fName := file.Name() + name := file.Name() err = file.Close() if err != nil { - t.Errorf("%v", err) + t.Error(err) } - fs, err := Stat(fName) + fs, err := Stat(name) if err != nil { t.Fatal(err) } - startAtime := Atime(fs) - startMtime := fs.ModTime() + + wantAtime := Atime(fs) + wantMtime := fs.ModTime() switch runtime.GOOS { case "js": - startAtime = startAtime.Truncate(time.Second) - startMtime = startMtime.Truncate(time.Second) - } - at0 := startAtime - mt0 := startMtime - t0 := startMtime.Truncate(time.Second).Add(1 * time.Hour) - - tests := []struct { - aTime time.Time - mTime time.Time - wantATime time.Time - wantMTime time.Time - }{ - { - aTime: time.Time{}, - mTime: time.Time{}, - wantATime: startAtime, - wantMTime: startMtime, - }, - { - aTime: t0.Add(200 * time.Second), - mTime: time.Time{}, - wantATime: t0.Add(200 * time.Second), - wantMTime: startMtime, - }, - { - aTime: time.Time{}, - mTime: t0.Add(100 * time.Second), - wantATime: t0.Add(200 * time.Second), - wantMTime: t0.Add(100 * time.Second), - }, - { - aTime: t0.Add(300 * time.Second), - mTime: t0.Add(100 * time.Second), - wantATime: t0.Add(300 * time.Second), - wantMTime: t0.Add(100 * time.Second), - }, + wantAtime = wantAtime.Truncate(time.Second) + wantMtime = wantMtime.Truncate(time.Second) } - for _, tt := range tests { - // Now change the times accordingly. - if err := Chtimes(fName, tt.aTime, tt.mTime); err != nil { - t.Error(err) - } + var setAtime, setMtime time.Time // Zero value means omit. + if !omitAt { + wantAtime = wantAtime.Add(-1 * time.Second) + setAtime = wantAtime + } + if !omitMt { + wantMtime = wantMtime.Add(-1 * time.Second) + setMtime = wantMtime + } - // Finally verify the expectations. - fs, err = Stat(fName) - if err != nil { - t.Error(err) - } - at0 = Atime(fs) - mt0 = fs.ModTime() + // Change the times accordingly. + if err := Chtimes(name, setAtime, setMtime); err != nil { + t.Error(err) + } - if got, want := at0, tt.wantATime; !got.Equal(want) { - errormsg := fmt.Sprintf("AccessTime mismatch with values ATime:%q-MTime:%q\ngot: %q\nwant: %q", tt.aTime, tt.mTime, got, want) - switch runtime.GOOS { - case "plan9": - // Mtime is the time of the last change of - // content. Similarly, atime is set whenever - // the contents are accessed; also, it is set - // whenever mtime is set. - case "windows": - t.Error(errormsg) - default: // unix's - if got, want := at0, tt.wantATime; !got.Equal(want) { - mounts, err := ReadFile("/bin/mounts") - if err != nil { - mounts, err = ReadFile("/etc/mtab") - } - if strings.Contains(string(mounts), "noatime") { - t.Log(errormsg) - t.Log("A filesystem is mounted with noatime; ignoring.") - } else { - switch runtime.GOOS { - case "netbsd", "dragonfly": - // On a 64-bit implementation, birth time is generally supported and cannot be changed. - // When supported, atime update is restricted and depends on the file system and on the - // OS configuration. - if strings.Contains(runtime.GOARCH, "64") { - t.Log(errormsg) - t.Log("Filesystem might not support atime changes; ignoring.") - } - default: - t.Error(errormsg) - } - } - } - } - } - if got, want := mt0, tt.wantMTime; !got.Equal(want) { - errormsg := fmt.Sprintf("ModTime mismatch with values ATime:%q-MTime:%q\ngot: %q\nwant: %q", tt.aTime, tt.mTime, got, want) - switch runtime.GOOS { - case "dragonfly": + // Verify the expectations. + fs, err = Stat(name) + if err != nil { + t.Error(err) + } + gotAtime := Atime(fs) + gotMtime := fs.ModTime() + + if !gotAtime.Equal(wantAtime) { + errormsg := fmt.Sprintf("atime mismatch, got: %q, want: %q", gotAtime, wantAtime) + switch runtime.GOOS { + case "plan9": + // Mtime is the time of the last change of content. + // Similarly, atime is set whenever the contents are + // accessed; also, it is set whenever mtime is set. + case "dragonfly": + if omitAt && omitMt { t.Log(errormsg) - t.Log("Mtime is always updated; ignoring.") - default: + t.Log("Known DragonFly BSD issue (won't work when both times are omitted); ignoring.") + } else { + // Assume hammer2 fs; https://www.dragonflybsd.org/hammer/ says: + // > Because HAMMER2 is a block copy-on-write filesystem, + // > the "atime" field is not supported and will typically + // > just reflect local system in-memory caches or mtime. + // + // TODO: if only can CI define TMPDIR to point to a tmpfs + // (e.g. /var/run/shm), this exception can be removed. + t.Log(errormsg) + t.Log("Known DragonFly BSD issue (atime not supported on hammer2); ignoring.") + } + case "netbsd": + if !omitAt && hasNoatime() { + t.Log(errormsg) + t.Log("Known NetBSD issue (atime not changed on fs mounted with noatime); ignoring.") + } else { t.Error(errormsg) } + default: + t.Error(errormsg) + } + } + if !gotMtime.Equal(wantMtime) { + errormsg := fmt.Sprintf("mtime mismatch, got: %q, want: %q", gotMtime, wantMtime) + switch runtime.GOOS { + case "dragonfly": + if omitAt && omitMt { + t.Log(errormsg) + t.Log("Known DragonFly BSD issue (won't work when both times are omitted); ignoring.") + } else { + t.Error(errormsg) + } + default: + t.Error(errormsg) } } } From 5f319b75075a62ab176ab8c25f0e45f2ae4f0704 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 Jun 2024 11:56:45 -0400 Subject: [PATCH 31/72] cmd/link: don't let dsymutil delete our temp directory To work around #59026, where dsymutil may not clean up its temp directory at exit, we set DSYMUTIL_REPRODUCER_PATH to our temp directory so it uses that, and we can delete it at the end. In Xcode 16 beta, dsymutil deletes the DSYMUTIL_REPRODUCER_PATH directory even if it is not empty. We still need our tmpdir at the point, so give a subdirectory to dsymutil instead. For #68088. Change-Id: I18759cc39512819bbd0511793ce917eae72245d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/593659 Reviewed-by: Than McIntosh LUCI-TryBot-Result: Go LUCI --- src/cmd/link/internal/ld/lib.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index c29a532bfd..fee7888b7c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2009,7 +2009,15 @@ func (ctxt *Link) hostlink() { cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym) // dsymutil may not clean up its temp directory at exit. // Set DSYMUTIL_REPRODUCER_PATH to work around. see issue 59026. - cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+*flagTmpdir) + // dsymutil (Apple LLVM version 16.0.0) deletes the directory + // even if it is not empty. We still need our tmpdir, so give a + // subdirectory to dsymutil. + dsymDir := filepath.Join(*flagTmpdir, "dsymutil") + err := os.MkdirAll(dsymDir, 0777) + if err != nil { + Exitf("fail to create temp dir: %v", err) + } + cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+dsymDir) if ctxt.Debugvlog != 0 { ctxt.Logf("host link dsymutil:") for _, v := range cmd.Args { From 5a18e79687dea15680ff5f799b549fa0efd0cad9 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 Jun 2024 12:20:38 -0400 Subject: [PATCH 32/72] cmd/link: don't skip code sign even if dsymutil didn't generate a file Even if dsymutil didn't generate a file (which should not happen with the Apple toolchain with the correct setup), we should not skip next steps, e.g. code sign. A return statement makes it exit too early. Updates #68088. Change-Id: Ic1271ed1b7fe5bdee5a25cc5d669a105173b389e Reviewed-on: https://go-review.googlesource.com/c/go/+/593660 LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/lib.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index fee7888b7c..4f1eebb9e3 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2050,14 +2050,13 @@ func (ctxt *Link) hostlink() { Exitf("%s: running strip failed: %v\n%s\n%s", os.Args[0], err, cmd, out) } // Skip combining if `dsymutil` didn't generate a file. See #11994. - if _, err := os.Stat(dsym); os.IsNotExist(err) { - return + if _, err := os.Stat(dsym); err == nil { + updateMachoOutFile("combining dwarf", + func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error { + return machoCombineDwarf(ctxt, exef, exem, dsym, outexe) + }) + uuidUpdated = true } - updateMachoOutFile("combining dwarf", - func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error { - return machoCombineDwarf(ctxt, exef, exem, dsym, outexe) - }) - uuidUpdated = true } if ctxt.IsDarwin() && !uuidUpdated && *flagBuildid != "" { updateMachoOutFile("rewriting uuid", From b0927fdd494a79458ff151ce8db59963f67b80be Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Fri, 28 Jun 2024 00:00:00 +0800 Subject: [PATCH 33/72] slices: update docs for All, Backward, Values For #61899 Change-Id: I3586b9b59e87159d21e1a270dabb3af213592739 Reviewed-on: https://go-review.googlesource.com/c/go/+/595515 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Alan Donovan Reviewed-by: Ian Lance Taylor --- src/slices/iter.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/slices/iter.go b/src/slices/iter.go index 131cece3a0..cd8f308ca0 100644 --- a/src/slices/iter.go +++ b/src/slices/iter.go @@ -9,8 +9,8 @@ import ( "iter" ) -// All returns an iterator over index-value pairs in the slice. -// The indexes range in the usual order, from 0 through len(s)-1. +// All returns an iterator over index-value pairs in the slice +// in the usual order. func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { return func(yield func(int, E) bool) { for i, v := range s { @@ -22,7 +22,7 @@ func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { } // Backward returns an iterator over index-value pairs in the slice, -// traversing it backward. The indexes range from len(s)-1 down to 0. +// traversing it backward with descending indices. func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { return func(yield func(int, E) bool) { for i := len(s) - 1; i >= 0; i-- { @@ -33,8 +33,7 @@ func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { } } -// Values returns an iterator over the slice elements, -// starting with s[0]. +// Values returns an iterator that yields the slice elements in order. func Values[Slice ~[]E, E any](s Slice) iter.Seq[E] { return func(yield func(E) bool) { for _, v := range s { From ea537cca314d9da5365eeefcc375410c76e93b36 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 27 Jun 2024 11:16:30 -0400 Subject: [PATCH 34/72] cmd/go/internal/help: add documentation for language version downgrading This change adds documentation for language version downgrading using build constraints. Fixes #68161 For #61894 Change-Id: I283a51afd7020c9fd1f5469a6a93fd814ba32f7e Reviewed-on: https://go-review.googlesource.com/c/go/+/595475 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/go/alldocs.go | 7 +++++++ src/cmd/go/internal/help/helpdoc.go | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 972f9e111f..e87e6ebe46 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1994,6 +1994,9 @@ // // //go:build // +// Build constraints can also be used to downgrade the language version +// used to compile a file. +// // Constraints may appear in any kind of source file (not just Go), but // they must appear near the top of the file, preceded // only by blank lines and other comments. These rules mean that in Go @@ -2116,6 +2119,10 @@ // with a "// +build" prefix. The gofmt command will add an equivalent //go:build // constraint when encountering the older syntax. // +// In modules with a Go version of 1.21 or later, if a file's build constraint +// has a term for a Go major release, the language version used when compiling +// the file will be the minimum version implied by the build constraint. +// // # Build modes // // The 'go build' and 'go install' commands take a -buildmode argument which diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 791013dbfe..29c0a56321 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -835,6 +835,9 @@ line comment that begins //go:build +Build constraints can also be used to downgrade the language version +used to compile a file. + Constraints may appear in any kind of source file (not just Go), but they must appear near the top of the file, preceded only by blank lines and other comments. These rules mean that in Go @@ -954,5 +957,9 @@ only when building the package for 32-bit x86. Go versions 1.16 and earlier used a different syntax for build constraints, with a "// +build" prefix. The gofmt command will add an equivalent //go:build constraint when encountering the older syntax. + +In modules with a Go version of 1.21 or later, if a file's build constraint +has a term for a Go major release, the language version used when compiling +the file will be the minimum version implied by the build constraint. `, } From 7f90b960a9711b51bf36f49be4274ac5f7e86a95 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 27 Jun 2024 20:45:22 -0700 Subject: [PATCH 35/72] cmd/compile: don't elide zero extension on top of signed values v = ... compute some value, which zeros top 32 bits ... w = zero-extend v We want to remove the zero-extension operation, as it doesn't do anything. But if v is typed as a signed value, and it gets spilled/restored, it might be re-sign-extended upon restore. So the zero-extend isn't actually a NOP when there might be calls or other reasons to spill in between v and w. Fixes #68227 Change-Id: I3b30b8e56c7d70deac1fb09d2becc7395acbadf8 Reviewed-on: https://go-review.googlesource.com/c/go/+/595675 LUCI-TryBot-Result: Go LUCI Reviewed-by: Joedian Reid Reviewed-by: Cuong Manh Le Reviewed-by: Cherry Mui --- src/cmd/compile/internal/ssa/rewrite.go | 17 ++++++++-- test/fixedbugs/issue68227.go | 43 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 test/fixedbugs/issue68227.go diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index aeec2b3768..5bc0308362 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -1287,6 +1287,11 @@ func areAdjacentOffsets(off1, off2, size int64) bool { // depth limits recursion depth. In AMD64.rules 3 is used as limit, // because it catches same amount of cases as 4. func zeroUpper32Bits(x *Value, depth int) bool { + if x.Type.IsSigned() && x.Type.Size() < 8 { + // If the value is signed, it might get re-sign-extended + // during spill and restore. See issue 68227. + return false + } switch x.Op { case OpAMD64MOVLconst, OpAMD64MOVLload, OpAMD64MOVLQZX, OpAMD64MOVLloadidx1, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVBload, OpAMD64MOVBloadidx1, @@ -1305,7 +1310,7 @@ func zeroUpper32Bits(x *Value, depth int) bool { case OpArg: // note: but not ArgIntReg // amd64 always loads args from the stack unsigned. // most other architectures load them sign/zero extended based on the type. - return x.Type.Size() == 4 && (x.Type.IsUnsigned() || x.Block.Func.Config.arch == "amd64") + return x.Type.Size() == 4 && x.Block.Func.Config.arch == "amd64" case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. @@ -1325,11 +1330,14 @@ func zeroUpper32Bits(x *Value, depth int) bool { // zeroUpper48Bits is similar to zeroUpper32Bits, but for upper 48 bits. func zeroUpper48Bits(x *Value, depth int) bool { + if x.Type.IsSigned() && x.Type.Size() < 8 { + return false + } switch x.Op { case OpAMD64MOVWQZX, OpAMD64MOVWload, OpAMD64MOVWloadidx1, OpAMD64MOVWloadidx2: return true case OpArg: // note: but not ArgIntReg - return x.Type.Size() == 2 && (x.Type.IsUnsigned() || x.Block.Func.Config.arch == "amd64") + return x.Type.Size() == 2 && x.Block.Func.Config.arch == "amd64" case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. @@ -1349,11 +1357,14 @@ func zeroUpper48Bits(x *Value, depth int) bool { // zeroUpper56Bits is similar to zeroUpper32Bits, but for upper 56 bits. func zeroUpper56Bits(x *Value, depth int) bool { + if x.Type.IsSigned() && x.Type.Size() < 8 { + return false + } switch x.Op { case OpAMD64MOVBQZX, OpAMD64MOVBload, OpAMD64MOVBloadidx1: return true case OpArg: // note: but not ArgIntReg - return x.Type.Size() == 1 && (x.Type.IsUnsigned() || x.Block.Func.Config.arch == "amd64") + return x.Type.Size() == 1 && x.Block.Func.Config.arch == "amd64" case OpPhi, OpSelect0, OpSelect1: // Phis can use each-other as an arguments, instead of tracking visited values, // just limit recursion depth. diff --git a/test/fixedbugs/issue68227.go b/test/fixedbugs/issue68227.go new file mode 100644 index 0000000000..615d2824e4 --- /dev/null +++ b/test/fixedbugs/issue68227.go @@ -0,0 +1,43 @@ +// run + +// Copyright 2024 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 main + +import ( + "fmt" +) + +type someType []uint64 + +func (s *someType) push(v uint64) { + *s = append(*s, v) +} + +func (s *someType) problematicFn(x1Lo, x1Hi, x2Lo, x2Hi uint64) { + r1 := int32(int16(x1Lo>>0)) * int32(int16(x2Lo>>0)) + g() + r3 := int32(int16(x1Lo>>32)) * int32(int16(x2Lo>>32)) + r4 := int32(int16(x1Lo>>48)) * int32(int16(x2Lo>>48)) + r5 := int32(int16(x1Hi>>0)) * int32(int16(x2Hi>>0)) + r7 := int32(int16(x1Hi>>32)) * int32(int16(x2Hi>>32)) + r8 := int32(int16(x1Hi>>48)) * int32(int16(x2Hi>>48)) + s.push(uint64(uint32(r1)) | (uint64(uint32(r3+r4)) << 32)) + s.push(uint64(uint32(r5)) | (uint64(uint32(r7+r8)) << 32)) +} + +//go:noinline +func g() { +} + +func main() { + s := &someType{} + s.problematicFn(0x1000100010001, 0x1000100010001, 0xffffffffffffffff, 0xffffffffffffffff) + for i := 0; i < 2; i++ { + if got, want := (*s)[i], uint64(0xfffffffeffffffff); got != want { + fmt.Printf("s[%d]=%x, want %x\n", i, got, want) + } + } +} From 773767def0e0f29584a69bd760430167b7479d7d Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Wed, 26 Jun 2024 01:35:13 +0800 Subject: [PATCH 36/72] net/http: avoid appending an existing trailing slash to path again This CL is similar to CL 562557, and it takes over CL 594175. While here, unrelatedly remove mapKeys function, use slices.Sorted(maps.Keys(ms)) to simplify code. Fixes #67657 Change-Id: Id8b99216f87a6dcfd6d5fa61407b515324c79112 Reviewed-on: https://go-review.googlesource.com/c/go/+/594737 LUCI-TryBot-Result: Go LUCI Reviewed-by: Jonathan Amsterdam Reviewed-by: Joedian Reid --- src/net/http/routing_tree_test.go | 5 ++--- src/net/http/serve_test.go | 16 ++++++++++++++++ src/net/http/server.go | 16 ++++------------ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/net/http/routing_tree_test.go b/src/net/http/routing_tree_test.go index 7de6b19507..f3f216357d 100644 --- a/src/net/http/routing_tree_test.go +++ b/src/net/http/routing_tree_test.go @@ -7,6 +7,7 @@ package http import ( "fmt" "io" + "maps" "strings" "testing" @@ -261,9 +262,7 @@ func TestMatchingMethods(t *testing.T) { t.Run(test.name, func(t *testing.T) { ms := map[string]bool{} test.tree.matchingMethods(test.host, test.path, ms) - keys := mapKeys(ms) - slices.Sort(keys) - got := strings.Join(keys, ",") + got := strings.Join(slices.Sorted(maps.Keys(ms)), ",") if got != test.want { t.Errorf("got %s, want %s", got, test.want) } diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 3ec10c2f14..b2858ba8f2 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -613,6 +613,22 @@ func TestMuxNoSlashRedirectWithTrailingSlash(t *testing.T) { } } +// Test that we don't attempt trailing-slash response 405 on a path that already has +// a trailing slash. +// See issue #67657. +func TestMuxNoSlash405WithTrailingSlash(t *testing.T) { + mux := NewServeMux() + mux.HandleFunc("GET /{x}/", func(w ResponseWriter, r *Request) { + fmt.Fprintln(w, "ok") + }) + w := httptest.NewRecorder() + req, _ := NewRequest("GET", "/", nil) + mux.ServeHTTP(w, req) + if g, w := w.Code, 404; g != w { + t.Errorf("got %d, want %d", g, w) + } +} + func TestShouldRedirectConcurrency(t *testing.T) { run(t, testShouldRedirectConcurrency) } func testShouldRedirectConcurrency(t *testing.T, mode testMode) { mux := NewServeMux() diff --git a/src/net/http/server.go b/src/net/http/server.go index a5e98f1d95..1ff72a0455 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -16,6 +16,7 @@ import ( "internal/godebug" "io" "log" + "maps" "math/rand" "net" "net/textproto" @@ -2721,19 +2722,10 @@ func (mux *ServeMux) matchingMethods(host, path string) []string { ms := map[string]bool{} mux.tree.matchingMethods(host, path, ms) // matchOrRedirect will try appending a trailing slash if there is no match. - mux.tree.matchingMethods(host, path+"/", ms) - methods := mapKeys(ms) - slices.Sort(methods) - return methods -} - -// TODO(jba): replace with maps.Keys when it is defined. -func mapKeys[K comparable, V any](m map[K]V) []K { - var ks []K - for k := range m { - ks = append(ks, k) + if !strings.HasSuffix(path, "/") { + mux.tree.matchingMethods(host, path+"/", ms) } - return ks + return slices.Sorted(maps.Keys(ms)) } // ServeHTTP dispatches the request to the handler whose From 82c371a307116450e9ab4dbce1853da3e69f4061 Mon Sep 17 00:00:00 2001 From: Alessandro Arzilli Date: Mon, 24 Jun 2024 15:53:55 +0200 Subject: [PATCH 37/72] cmd/compile: drop internal range-over-func vars from DWARF output Drops internal range-over-func variables from the DWARF output (excluding #yield which is used by Delve). Fixes #68238 Change-Id: Ic035e37ca3560347276cdc3b469fd564da33f4f5 Reviewed-on: https://go-review.googlesource.com/c/go/+/594257 Reviewed-by: Than McIntosh Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Hyang-Ah Hana Kim Auto-Submit: Hyang-Ah Hana Kim --- src/cmd/compile/internal/dwarfgen/dwarf.go | 6 ++++ src/cmd/compile/internal/rangefunc/rewrite.go | 2 +- src/cmd/compile/internal/ssa/debug.go | 30 ++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index 512d8d22e7..36cc253e82 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -91,6 +91,9 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn obj.Func) (scopes []dwarf.Sc default: continue } + if !ssa.IsVarWantedForDebug(n) { + continue + } apdecls = append(apdecls, n) if n.Type().Kind() == types.TSSA { // Can happen for TypeInt128 types. This only happens for @@ -194,6 +197,9 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir // DWARF-gen. See issue 48573 for more details. debugInfo := fn.DebugInfo.(*ssa.FuncDebug) for _, n := range debugInfo.RegOutputParams { + if !ssa.IsVarWantedForDebug(n) { + continue + } if n.Class != ir.PPARAMOUT || !n.IsOutputParamInRegisters() { panic("invalid ir.Name on debugInfo.RegOutputParams list") } diff --git a/src/cmd/compile/internal/rangefunc/rewrite.go b/src/cmd/compile/internal/rangefunc/rewrite.go index e5a0b9f8af..ba2eb8d0fd 100644 --- a/src/cmd/compile/internal/rangefunc/rewrite.go +++ b/src/cmd/compile/internal/rangefunc/rewrite.go @@ -1137,7 +1137,7 @@ func (r *rewriter) setStateAt(index int, stateVal abi.RF_State) *syntax.AssignSt func (r *rewriter) bodyFunc(body []syntax.Stmt, lhs []syntax.Expr, def bool, ftyp *types2.Signature, start, end syntax.Pos) *syntax.FuncLit { // Starting X(bodyFunc); build up bodyFunc first. var params, results []*types2.Var - results = append(results, types2.NewVar(start, nil, "", r.bool.Type())) + results = append(results, types2.NewVar(start, nil, "#r", r.bool.Type())) bodyFunc := &syntax.FuncLit{ // Note: Type is ignored but needs to be non-nil to avoid panic in syntax.Inspect. Type: &syntax.FuncType{}, diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go index 4abe5a9892..04025f7882 100644 --- a/src/cmd/compile/internal/ssa/debug.go +++ b/src/cmd/compile/internal/ssa/debug.go @@ -600,7 +600,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func( state.vars = state.vars[:0] for i, slot := range f.Names { state.slots = append(state.slots, *slot) - if ir.IsSynthetic(slot.N) { + if ir.IsSynthetic(slot.N) || !IsVarWantedForDebug(slot.N) { continue } @@ -620,7 +620,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func( for _, v := range b.Values { if v.Op == OpVarDef { n := v.Aux.(*ir.Name) - if ir.IsSynthetic(n) { + if ir.IsSynthetic(n) || !IsVarWantedForDebug(n) { continue } @@ -665,7 +665,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingLevel int, stackOffset func( state.initializeCache(f, len(state.varParts), len(state.slots)) for i, slot := range f.Names { - if ir.IsSynthetic(slot.N) { + if ir.IsSynthetic(slot.N) || !IsVarWantedForDebug(slot.N) { continue } for _, value := range f.NamedValues[*slot] { @@ -1087,7 +1087,7 @@ func (state *debugState) processValue(v *Value, vSlots []SlotID, vReg *Register) switch { case v.Op == OpVarDef: n := v.Aux.(*ir.Name) - if ir.IsSynthetic(n) { + if ir.IsSynthetic(n) || !IsVarWantedForDebug(n) { break } @@ -1835,6 +1835,9 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta // will be sorted out elsewhere continue } + if !IsVarWantedForDebug(inp.Name) { + continue + } addVarSlot(inp.Name, inp.Type) params = append(params, inp) } @@ -1855,6 +1858,9 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta // will be sorted out elsewhere continue } + if !IsVarWantedForDebug(inp.Name) { + continue + } sl := rval.Slots[pidx] n := rval.Vars[pidx] @@ -1948,3 +1954,19 @@ func BuildFuncDebugNoOptimized(ctxt *obj.Link, f *Func, loggingEnabled bool, sta pidx++ } } + +// IsVarWantedForDebug returns true if the debug info for the node should +// be generated. +// For example, internal variables for range-over-func loops have little +// value to users, so we don't generate debug info for them. +func IsVarWantedForDebug(n ir.Node) bool { + name := n.Sym().Name + if len(name) > 0 && name[0] == '&' { + name = name[1:] + } + if len(name) > 0 && name[0] == '#' { + // #yield is used by delve. + return strings.HasPrefix(name, "#yield") + } + return true +} From c33144c47cbee5506df404553c3769867972f889 Mon Sep 17 00:00:00 2001 From: Tom Levy Date: Mon, 13 May 2024 04:10:34 +0000 Subject: [PATCH 38/72] runtime: fix nil pointer in TestGoroutineParallelism2 when offline Previously, the test would crash when running on a computer without an internet connection, e.g. in airplane mode (stack trace below). The bug was that the condition was inverted. The code tried to close the listener if `err != nil` (that is, if net.Listen() failed). But if Listen() failed then there is no listener to close! The listener should only be closed if Listen() succeeded. Here is the stack trace from `go test runtime` when offline: ``` --- FAIL: TestGoroutineParallelism2 (0.16s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x7bdaa1] goroutine 3858 gp=0xc000185180 m=5 mp=0xc000100008 [running]: panic({0x854960?, 0xbf70b0?}) /src/runtime/panic.go:778 +0x168 fp=0xc0000afad8 sp=0xc0000afa28 pc=0x441bc8 testing.tRunner.func1.2({0x854960, 0xbf70b0}) /src/testing/testing.go:1632 +0x230 fp=0xc0000afb88 sp=0xc0000afad8 pc=0x524090 testing.tRunner.func1() /src/testing/testing.go:1635 +0x35e fp=0xc0000afd18 sp=0xc0000afb88 pc=0x523a7e panic({0x854960?, 0xbf70b0?}) /src/runtime/panic.go:759 +0x132 fp=0xc0000afdc8 sp=0xc0000afd18 pc=0x441b92 runtime.panicmem(...) /src/runtime/panic.go:261 runtime.sigpanic() /src/runtime/signal_unix.go:900 +0x359 fp=0xc0000afe28 sp=0xc0000afdc8 pc=0x483c79 runtime_test.testGoroutineParallelism2(0x522e13?, 0x0, 0x1) /src/runtime/proc_test.go:204 +0x221 fp=0xc0000aff50 sp=0xc0000afe28 pc=0x7bdaa1 runtime_test.TestGoroutineParallelism2(0xc000221520) /src/runtime/proc_test.go:151 +0x30 fp=0xc0000aff70 sp=0xc0000aff50 pc=0x7bd850 testing.tRunner(0xc000221520, 0x8fed88) /src/testing/testing.go:1690 +0xf4 fp=0xc0000affc0 sp=0xc0000aff70 pc=0x523674 testing.(*T).Run.gowrap1() /src/testing/testing.go:1743 +0x25 fp=0xc0000affe0 sp=0xc0000affc0 pc=0x524665 runtime.goexit({}) /src/runtime/asm_amd64.s:1700 +0x1 fp=0xc0000affe8 sp=0xc0000affe0 pc=0x487a41 created by testing.(*T).Run in goroutine 1 /src/testing/testing.go:1743 +0x390 ``` Change-Id: I48983fe21b3360ea9d0182c4a3b509801257027b Reviewed-on: https://go-review.googlesource.com/c/go/+/584436 LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Reviewed-by: Than McIntosh Reviewed-by: Keith Randall --- src/runtime/proc_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/proc_test.go b/src/runtime/proc_test.go index 67eadeac9e..a930ea707f 100644 --- a/src/runtime/proc_test.go +++ b/src/runtime/proc_test.go @@ -200,7 +200,7 @@ func testGoroutineParallelism2(t *testing.T, load, netpoll bool) { laddr = "127.0.0.1:0" } ln, err := net.Listen("tcp", laddr) - if err != nil { + if err == nil { defer ln.Close() // yup, defer in a loop } } From cdbf5f2f7e968993560730479d4670c2d6eecd8b Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Sat, 29 Jun 2024 20:35:40 +0000 Subject: [PATCH 39/72] sync: refer to Locker interface methods in RWMutex.RLocker doc The methods being implemented are part of the Locker interface, not the RWMutex struct. Fixes #68250. Change-Id: I609c4d5c44e90a12914a8678971ba295519cc265 Reviewed-on: https://go-review.googlesource.com/c/go/+/595875 Auto-Submit: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/sync/rwmutex.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sync/rwmutex.go b/src/sync/rwmutex.go index 66cb93c44e..1d5b8fde4a 100644 --- a/src/sync/rwmutex.go +++ b/src/sync/rwmutex.go @@ -234,7 +234,7 @@ func syscall_hasWaitingReaders(rw *RWMutex) bool { } // RLocker returns a [Locker] interface that implements -// the [RWMutex.Lock] and [RWMutex.Unlock] methods by calling rw.RLock and rw.RUnlock. +// the [Locker.Lock] and [Locker.Unlock] methods by calling rw.RLock and rw.RUnlock. func (rw *RWMutex) RLocker() Locker { return (*rlocker)(rw) } From d3c93f2f00fe40eb6f8b0bf9c81b15ddd9872119 Mon Sep 17 00:00:00 2001 From: Mohamed Yousif Date: Mon, 24 Jun 2024 16:14:03 +0000 Subject: [PATCH 40/72] cmd/go: update go clean help message Update the help message for the go clean command to include the correct usage and flags for better clarity. This change follows instructions by Ian on this thread . Change-Id: Ia509a38ee9ec7c31d384c3563535c5e3ccd9a9ce GitHub-Last-Rev: 3048b2e4bd10a8d25da479f96c9d90ecb3c63082 GitHub-Pull-Request: golang/go#68135 Reviewed-on: https://go-review.googlesource.com/c/go/+/593639 LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Michael Matloob Commit-Queue: Ian Lance Taylor Reviewed-by: Than McIntosh --- src/cmd/go/alldocs.go | 2 +- src/cmd/go/internal/clean/clean.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index e87e6ebe46..2840ba6ea9 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -276,7 +276,7 @@ // // Usage: // -// go clean [clean flags] [build flags] [packages] +// go clean [-i] [-r] [-cache] [-testcache] [-modcache] [-fuzzcache] [build flags] [packages] // // Clean removes object files from package source directories. // The go command builds most objects in a temporary directory, diff --git a/src/cmd/go/internal/clean/clean.go b/src/cmd/go/internal/clean/clean.go index de2ef9dcb9..3b5924fe13 100644 --- a/src/cmd/go/internal/clean/clean.go +++ b/src/cmd/go/internal/clean/clean.go @@ -28,7 +28,7 @@ import ( ) var CmdClean = &base.Command{ - UsageLine: "go clean [clean flags] [build flags] [packages]", + UsageLine: "go clean [-i] [-r] [-cache] [-testcache] [-modcache] [-fuzzcache] [build flags] [packages]", Short: "remove object files and cached files", Long: ` Clean removes object files from package source directories. From f71c00b6165177dbcc5d40ff5f4731d297ee6090 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Mon, 1 Jul 2024 16:11:33 +0000 Subject: [PATCH 41/72] cmd/link: align .reloc block starts by 32 bits for PE target Tweak the code that emits the PE ".reloc" section on Windows to ensure that each relocation block is 32-bit aligned, which is required by the PE standard. Fixes #68260. Change-Id: I39b75a7491b00fa97871aebb90d3be0ec09f9c40 Reviewed-on: https://go-review.googlesource.com/c/go/+/595896 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/cmd/link/internal/ld/pe.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 8cfecafe84..14f0485530 100644 --- a/src/cmd/link/internal/ld/pe.go +++ b/src/cmd/link/internal/ld/pe.go @@ -1548,8 +1548,21 @@ func (rt *peBaseRelocTable) write(ctxt *Link) { // sort the pages array sort.Sort(rt.pages) + // .reloc section must be 32-bit aligned + if out.Offset()&3 != 0 { + Errorf(nil, "internal error, start of .reloc not 32-bit aligned") + } + for _, p := range rt.pages { b := rt.blocks[p] + + // Add a dummy entry at the end of the list if we have an + // odd number of entries, so as to ensure that the next + // block starts on a 32-bit boundary (see issue 68260). + if len(b.entries)&1 != 0 { + b.entries = append(b.entries, peBaseRelocEntry{}) + } + const sizeOfPEbaseRelocBlock = 8 // 2 * sizeof(uint32) blockSize := uint32(sizeOfPEbaseRelocBlock + len(b.entries)*2) out.Write32(p) From 94982a07825aec711f11c97283e99e467838d616 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 1 Jul 2024 14:13:21 -0400 Subject: [PATCH 42/72] cmd/go/internal/workcmd: remove a potentially confusing statement A statement in the go work use docs that was meant to clarify that go work use would clean up use statements where the directories did not exist ended up causing confusion. Remove that statement for now. We might want to add something back in the future. For #68245 Change-Id: I7f6646b5dd05c18aa15e0e54f2816753f318404e Reviewed-on: https://go-review.googlesource.com/c/go/+/595536 LUCI-TryBot-Result: Go LUCI Reviewed-by: Eli Bendersky --- src/cmd/go/alldocs.go | 3 +-- src/cmd/go/internal/workcmd/use.go | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 2840ba6ea9..75e6d65d0c 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1689,8 +1689,7 @@ // // The -r flag searches recursively for modules in the argument // directories, and the use command operates as if each of the directories -// were specified as arguments: namely, use directives will be added for -// directories that exist, and removed for directories that do not exist. +// were specified as arguments. // // See the workspaces reference at https://go.dev/ref/mod#workspaces // for more information. diff --git a/src/cmd/go/internal/workcmd/use.go b/src/cmd/go/internal/workcmd/use.go index 55477119d4..0cdbed6b18 100644 --- a/src/cmd/go/internal/workcmd/use.go +++ b/src/cmd/go/internal/workcmd/use.go @@ -42,8 +42,7 @@ thing that go work use does. The -r flag searches recursively for modules in the argument directories, and the use command operates as if each of the directories -were specified as arguments: namely, use directives will be added for -directories that exist, and removed for directories that do not exist. +were specified as arguments. From 09aeb6e33ab426eff4676a3baf694d5a3019e9fc Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Mon, 1 Jul 2024 12:41:56 -0700 Subject: [PATCH 43/72] os: add TODO about removing test exception TestChtimesOmit excludes the failure on DragonFly BSD when both atime and mtime are omitted. The relevant Dragonfly BSD bug is now fixed in git (see [1]). Add a TODO comment to remove the exclusion from the test once the fix is generally available. This comment also addresses the question why the exception exists. Amends CL 591535. [1]: https://github.com/DragonFlyBSD/DragonFlyBSD/commit/c7c71870ed0 Change-Id: I3b53582301d44feb76b53788aa337c380ba82592 Reviewed-on: https://go-review.googlesource.com/c/go/+/595958 Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/os/os_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/os/os_test.go b/src/os/os_test.go index 9519aa0fc6..878974384d 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1440,6 +1440,9 @@ func testChtimesOmit(t *testing.T, omitAt, omitMt bool) { gotAtime := Atime(fs) gotMtime := fs.ModTime() + // TODO: remove the dragonfly omitAt && omitMt exceptions below once the + // fix (https://github.com/DragonFlyBSD/DragonFlyBSD/commit/c7c71870ed0) + // is available generally and on CI runners. if !gotAtime.Equal(wantAtime) { errormsg := fmt.Sprintf("atime mismatch, got: %q, want: %q", gotAtime, wantAtime) switch runtime.GOOS { From f12ac5be7045efcde39025c32cc01a20a305012c Mon Sep 17 00:00:00 2001 From: Darin Krauss Date: Mon, 1 Jul 2024 13:25:28 -0400 Subject: [PATCH 44/72] time: fix time zone parsing when format includes time zone seconds The current implementation fails to parse a time string with a "Z" time zone using a time format that includes time zone seconds. This fix correctly parses the "Z" time zone for any Z-base time format that includes seconds (i.e. "Z070000" or "Z07:00:00"). Fixes #68263 Change-Id: Idf8fa06b5f96383f050c4ffbd2bc5804fd408650 Reviewed-on: https://go-review.googlesource.com/c/go/+/595897 Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/time/format.go | 6 ++++-- src/time/format_test.go | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/time/format.go b/src/time/format.go index 6488ec8aba..c9e68b3eb2 100644 --- a/src/time/format.go +++ b/src/time/format.go @@ -1203,12 +1203,14 @@ func parse(layout, value string, defaultLocation, local *Location) (Time, error) default: err = errBad } - case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ: - if (std == stdISO8601TZ || std == stdISO8601ShortTZ || std == stdISO8601ColonTZ) && len(value) >= 1 && value[0] == 'Z' { + case stdISO8601TZ, stdISO8601ShortTZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ColonSecondsTZ: + if len(value) >= 1 && value[0] == 'Z' { value = value[1:] z = UTC break } + fallthrough + case stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ: var sign, hour, min, seconds string if std == stdISO8601ColonTZ || std == stdNumColonTZ { if len(value) < 6 { diff --git a/src/time/format_test.go b/src/time/format_test.go index 4b598f6bdf..2537c76596 100644 --- a/src/time/format_test.go +++ b/src/time/format_test.go @@ -336,6 +336,23 @@ var parseTests = []ParseTest{ {"", "2006-002 15:04:05", "2010-035 21:00:57", false, false, 1, 0}, {"", "200600201 15:04:05", "201003502 21:00:57", false, false, 1, 0}, {"", "200600204 15:04:05", "201003504 21:00:57", false, false, 1, 0}, + + // Time zone offsets + {"", "2006-01-02T15:04:05Z07", "2010-02-04T21:00:57Z", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07", "2010-02-04T21:00:57+08", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07", "2010-02-04T21:00:57-08", true, false, 1, 0}, + {"", "2006-01-02T15:04:05Z0700", "2010-02-04T21:00:57Z", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z0700", "2010-02-04T21:00:57+0800", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z0700", "2010-02-04T21:00:57-0800", true, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07:00", "2010-02-04T21:00:57Z", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07:00", "2010-02-04T21:00:57+08:00", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07:00", "2010-02-04T21:00:57-08:00", true, false, 1, 0}, + {"", "2006-01-02T15:04:05Z070000", "2010-02-04T21:00:57Z", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z070000", "2010-02-04T21:00:57+080000", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z070000", "2010-02-04T21:00:57-080000", true, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07:00:00", "2010-02-04T21:00:57Z", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07:00:00", "2010-02-04T21:00:57+08:00:00", false, false, 1, 0}, + {"", "2006-01-02T15:04:05Z07:00:00", "2010-02-04T21:00:57-08:00:00", true, false, 1, 0}, } func TestParse(t *testing.T) { From 148755a27b50134d1db72c3c0bdf500815569531 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 2 Jul 2024 11:44:43 -0700 Subject: [PATCH 45/72] cmd/link: document -checklinkname option For #67401 Change-Id: I04bff1c942a4033325450c0b7dddc7980f3373cc Reviewed-on: https://go-review.googlesource.com/c/go/+/596216 Auto-Submit: Ian Lance Taylor Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/cmd/link/doc.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/link/doc.go b/src/cmd/link/doc.go index bd620f9878..9ec2c002f4 100644 --- a/src/cmd/link/doc.go +++ b/src/cmd/link/doc.go @@ -55,6 +55,10 @@ Flags: Set build mode (default exe). -c Dump call graphs. + -checklinkname=value + If value is 0, all go:linkname directives are permitted. + If value is 1 (the default), only a known set of widely-used + linknames are permitted. -compressdwarf Compress DWARF if possible (default true). -cpuprofile file From 71f9dbb1e409a28680f40c60fad5a386ed92a096 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 3 Jul 2024 13:13:05 +0700 Subject: [PATCH 46/72] cmd/compile: emit error message on mismatch import path Fixes #54542 Change-Id: I16cfb84fc54892923106d0a6f0b3ba810886d077 Reviewed-on: https://go-review.googlesource.com/c/go/+/596396 Auto-Submit: Cuong Manh Le LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Than McIntosh --- src/cmd/compile/internal/noder/unified.go | 6 +- test/fixedbugs/issue54542.go | 67 +++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue54542.go diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index 22d6f71329..6bc23cc5f9 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -7,6 +7,7 @@ package noder import ( "fmt" "internal/pkgbits" + "internal/types/errors" "io" "runtime" "sort" @@ -403,7 +404,10 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) { r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) pkg := r.pkg() - base.Assertf(pkg == importpkg, "have package %q (%p), want package %q (%p)", pkg.Path, pkg, importpkg.Path, importpkg) + if pkg != importpkg { + base.ErrorfAt(base.AutogeneratedPos, errors.BadImportPath, "mismatched import path, have %q (%p), want %q (%p)", pkg.Path, pkg, importpkg.Path, importpkg) + base.ErrorExit() + } r.Bool() // TODO(mdempsky): Remove; was "has init" diff --git a/test/fixedbugs/issue54542.go b/test/fixedbugs/issue54542.go new file mode 100644 index 0000000000..165bcc582e --- /dev/null +++ b/test/fixedbugs/issue54542.go @@ -0,0 +1,67 @@ +// run + +//go:build !js && !wasip1 + +// Copyright 2024 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 main + +import ( + "bytes" + "fmt" + "os" + "os/exec" + "path/filepath" +) + +const aSrc = `package a + +func A() { println("a") } +` + +const mainSrc = `package main + +import "a" + +func main() { a.A() } +` + +var srcs = map[string]string{ + "a.go": aSrc, + "main.go": mainSrc, +} + +func main() { + dir, err := os.MkdirTemp("", "issue54542") + if err != nil { + panic(err) + } + defer os.RemoveAll(dir) + + for fn, src := range srcs { + if err := os.WriteFile(filepath.Join(dir, fn), []byte(src), 0644); err != nil { + panic(err) + } + } + + if _, err := runInDir(dir, "tool", "compile", "-p=lie", "a.go"); err != nil { + panic(err) + } + + out, err := runInDir(dir, "tool", "compile", "-I=.", "-p=main", "main.go") + if err == nil { + panic("compiling succeed unexpectedly") + } + + if bytes.Contains(out, []byte("internal compiler error:")) { + panic(fmt.Sprintf("unexpected ICE:\n%s", string(out))) + } +} + +func runInDir(dir string, args ...string) ([]byte, error) { + cmd := exec.Command("go", args...) + cmd.Dir = dir + return cmd.CombinedOutput() +} From 5f50b1e3bf710b4107eb38496d932b3d9bd1fc98 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 25 Jun 2024 02:35:19 +0700 Subject: [PATCH 47/72] cmd/compile: fix mis-compilation when switching over channels CL 418101 changes Unified IR writer to force mixed tag/case to have common type, emitting the implicit conversion if any of the case values are not assignable to the tag value's type. However, the Go spec definition of equality is non-transitive for channels stored in interfaces, causing incorrect behavior with channel values comparison. To fix it, don't emit the implicit conversions if tag type is channel. Fixes #67190 Change-Id: I9a29d9ce3c7978f0689e9502ba6f15660c763d16 Reviewed-on: https://go-review.googlesource.com/c/go/+/594575 Auto-Submit: Cuong Manh Le Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/cmd/compile/internal/noder/writer.go | 26 +++++++++++++++++------- test/fixedbugs/issue67190.go | 24 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 test/fixedbugs/issue67190.go diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index fe8f8f2a35..8fed138a4a 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1582,6 +1582,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { w.stmt(stmt.Init) var iface, tagType types2.Type + var tagTypeIsChan bool if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) { iface = w.p.typeOf(guard.X) @@ -1603,6 +1604,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { tv := w.p.typeAndValue(tag) tagType = tv.Type tagValue = tv.Value + _, tagTypeIsChan = tagType.Underlying().(*types2.Chan) } else { tagType = types2.Typ[types2.Bool] tagValue = constant.MakeBool(true) @@ -1655,12 +1657,18 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { // have the same type. If there are any case values that can't be // converted to the tag value's type, then convert everything to // `any` instead. - Outer: - for _, clause := range stmt.Body { - for _, cas := range syntax.UnpackListExpr(clause.Cases) { - if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) { - tagType = types2.NewInterfaceType(nil, nil) - break Outer + // + // Except that we need to keep comparisons of channel values from + // being wrapped in any(). See issue #67190. + + if !tagTypeIsChan { + Outer: + for _, clause := range stmt.Body { + for _, cas := range syntax.UnpackListExpr(clause.Cases) { + if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) { + tagType = types2.NewInterfaceType(nil, nil) + break Outer + } } } } @@ -1696,7 +1704,11 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { w.Sync(pkgbits.SyncExprs) w.Len(len(cases)) for _, cas := range cases { - w.implicitConvExpr(tagType, cas) + typ := tagType + if tagTypeIsChan { + typ = nil + } + w.implicitConvExpr(typ, cas) } } diff --git a/test/fixedbugs/issue67190.go b/test/fixedbugs/issue67190.go new file mode 100644 index 0000000000..c19b248b51 --- /dev/null +++ b/test/fixedbugs/issue67190.go @@ -0,0 +1,24 @@ +// run + +// Copyright 2024 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 main + +func main() { + ch1 := make(chan struct{}) + var ch2 <-chan struct{} = ch1 + + switch ch1 { + case ch2: + default: + panic("bad narrow case") + } + + switch ch2 { + case ch1: + default: + panic("bad narrow switch") + } +} From 7d19d508a994be9731e27b14b6ecc13ccf527138 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 3 Jul 2024 11:20:54 -0700 Subject: [PATCH 48/72] cmd/cgo: read CGO_LDFLAGS environment variable For #66456 we changed from the CGO_LDFLAGS environment variable to the -ldflags option. This broke Bazel, which uses CGO_LDFLAGS. So restore reading CGO_LDFLAGS for now. For #66456 Change-Id: Iebdd8bde1c7c18da09c6370e284c7ac7fa08fc54 Reviewed-on: https://go-review.googlesource.com/c/go/+/596615 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Commit-Queue: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Reviewed-by: Cherry Mui --- src/cmd/cgo/main.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 156038b33b..5699cc55be 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -343,6 +343,21 @@ func main() { p.addToFlag("LDFLAGS", args) } + // For backward compatibility for Bazel, record CGO_LDFLAGS + // from the environment for external linking. + // This should not happen with cmd/go, which removes CGO_LDFLAGS + // from the environment when invoking cgo. + // This can be removed when we no longer need to support + // older versions of Bazel. See issue #66456 and + // https://github.com/bazelbuild/rules_go/issues/3979. + if envFlags := os.Getenv("CGO_LDFLAGS"); envFlags != "" { + args, err := splitQuoted(envFlags) + if err != nil { + fatalf("bad CGO_LDFLAGS: %q (%s)", envFlags, err) + } + p.addToFlag("LDFLAGS", args) + } + // Need a unique prefix for the global C symbols that // we use to coordinate between gcc and ourselves. // We already put _cgo_ at the beginning, so the main From 82c14346d89ec0eeca114f9ca0e88516b2cda454 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Wed, 3 Jul 2024 14:14:34 -0400 Subject: [PATCH 49/72] cmd/link: don't disable memory profiling when pprof.WriteHeapProfile is used We have an optimization that if the memory profile is not consumed anywhere, we set the memory profiling rate to 0 to disable the "background" low-rate profiling. We detect whether the memory profile is used by checking whether the runtime.MemProfile function is reachable at link time. Previously, all APIs that access the memory profile go through runtime.MemProfile. But the code was refactored in CL 572396, and now the legacy entry point WriteHeapProfile uses pprof_memProfileInternal without going through runtime.MemProfile. In fact, even with the recommended runtime/pprof.Profile API (pprof.Lookup or pprof.Profiles), runtime.MemProfile is only (happen to be) reachable through countHeap. Change the linker to check runtime.memProfileInternal instead, which is on all code paths that retrieve the memory profile. Add a test case for WriteHeapProfile, so we cover all entry points. Fixes #68136. Change-Id: I075c8d45c95c81825a1822f032e23107aea4303c Reviewed-on: https://go-review.googlesource.com/c/go/+/596538 Reviewed-by: Than McIntosh LUCI-TryBot-Result: Go LUCI --- src/cmd/link/internal/ld/ld_test.go | 29 ++++++++++++++++++++++++++++- src/cmd/link/internal/ld/lib.go | 4 ++-- src/runtime/mprof.go | 10 +++++++++- src/runtime/pprof/pprof.go | 3 ++- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/cmd/link/internal/ld/ld_test.go b/src/cmd/link/internal/ld/ld_test.go index 1767667759..c954ab6bca 100644 --- a/src/cmd/link/internal/ld/ld_test.go +++ b/src/cmd/link/internal/ld/ld_test.go @@ -304,7 +304,34 @@ package main import "runtime" import "runtime/pprof" func main() { - _ = pprof.Profiles() + _ = pprof.Profiles() + println(runtime.MemProfileRate) +} +`, + "524288", + }, + { + "with_memprofile_runtime_pprof_writeheap", + ` +package main +import "io" +import "runtime" +import "runtime/pprof" +func main() { + _ = pprof.WriteHeapProfile(io.Discard) + println(runtime.MemProfileRate) +} +`, + "524288", + }, + { + "with_memprofile_runtime_pprof_lookupheap", + ` +package main +import "runtime" +import "runtime/pprof" +func main() { + _ = pprof.Lookup("heap") println(runtime.MemProfileRate) } `, diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 4f1eebb9e3..d66027387b 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -892,9 +892,9 @@ func (ctxt *Link) linksetup() { } // Set runtime.disableMemoryProfiling bool if - // runtime.MemProfile is not retained in the binary after + // runtime.memProfileInternal is not retained in the binary after // deadcode (and we're not dynamically linking). - memProfile := ctxt.loader.Lookup("runtime.MemProfile", abiInternalVer) + memProfile := ctxt.loader.Lookup("runtime.memProfileInternal", abiInternalVer) if memProfile != 0 && !ctxt.loader.AttrReachable(memProfile) && !ctxt.DynlinkingGo() { memProfSym := ctxt.loader.LookupOrCreateSym("runtime.disableMemoryProfiling", 0) sb := ctxt.loader.MakeSymbolUpdater(memProfSym) diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index b51a1ad3ce..b4fe0e5549 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -892,9 +892,10 @@ func (r *StackRecord) Stack() []uintptr { // at the beginning of main). var MemProfileRate int = 512 * 1024 -// disableMemoryProfiling is set by the linker if runtime.MemProfile +// disableMemoryProfiling is set by the linker if memory profiling // is not used and the link type guarantees nobody else could use it // elsewhere. +// We check if the runtime.memProfileInternal symbol is present. var disableMemoryProfiling bool // A MemProfileRecord describes the live objects allocated @@ -955,6 +956,13 @@ func MemProfile(p []MemProfileRecord, inuseZero bool) (n int, ok bool) { // memProfileInternal returns the number of records n in the profile. If there // are less than size records, copyFn is invoked for each record, and ok returns // true. +// +// The linker set disableMemoryProfiling to true to disable memory profiling +// if this function is not reachable. Mark it noinline to ensure the symbol exists. +// (This function is big and normally not inlined anyway.) +// See also disableMemoryProfiling above and cmd/link/internal/ld/lib.go:linksetup. +// +//go:noinline func memProfileInternal(size int, inuseZero bool, copyFn func(profilerecord.MemProfileRecord)) (n int, ok bool) { cycle := mProfCycle.read() // If we're between mProf_NextCycle and mProf_Flush, take care diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index be17e59875..d3af5bba91 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -586,7 +586,8 @@ func writeHeapInternal(w io.Writer, debug int, defaultSampleType string) error { runtime.ReadMemStats(memStats) } - // Find out how many records there are (MemProfile(nil, true)), + // Find out how many records there are (the call + // pprof_memProfileInternal(nil, true) below), // allocate that many records, and get the data. // There's a race—more records might be added between // the two calls—so allocate a few extra records for safety From be152920b90dd0fd73e2b2d6ffea294e09fc36be Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 2 Jul 2024 17:17:39 +0700 Subject: [PATCH 50/72] cmd/compile: fix ICE when compiling global a, b = f() CL 327651 rewrites a, b = f() to use temporaries when types are not identical. That would leave OAS2 node appears in body of init function for global variables initialization. The staticinit pass is not updated to handle OAS2 node, causing ICE when compiling global variables. To fix this, handle OAS2 nodes like other OAS2*, since they mostly necessitate dynamic execution anyway. Fixes #68264 Change-Id: I1eff8cc3e47035738a2c70d3169e35ec36ee9242 Reviewed-on: https://go-review.googlesource.com/c/go/+/596055 Reviewed-by: Than McIntosh Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Auto-Submit: Cuong Manh Le --- src/cmd/compile/internal/staticinit/sched.go | 14 ++++++++++++++ test/fixedbugs/issue68264.go | 15 +++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/fixedbugs/issue68264.go diff --git a/src/cmd/compile/internal/staticinit/sched.go b/src/cmd/compile/internal/staticinit/sched.go index 7317ed1fec..91c0a27faf 100644 --- a/src/cmd/compile/internal/staticinit/sched.go +++ b/src/cmd/compile/internal/staticinit/sched.go @@ -107,6 +107,20 @@ func (s *Schedule) tryStaticInit(n ir.Node) bool { case ir.OAS: n := n.(*ir.AssignStmt) lhs, rhs = []ir.Node{n.X}, n.Y + case ir.OAS2: + // Usually OAS2 has been rewritten to separate OASes by types2. + // What's left here is "var a, b = tmp1, tmp2" as a result from rewriting + // "var a, b = f()" that needs type conversion, which is not static. + n := n.(*ir.AssignListStmt) + for _, rhs := range n.Rhs { + for rhs.Op() == ir.OCONVNOP { + rhs = rhs.(*ir.ConvExpr).X + } + if name, ok := rhs.(*ir.Name); !ok || !name.AutoTemp() { + base.FatalfAt(n.Pos(), "unexpected rhs, not an autotmp: %+v", rhs) + } + } + return false case ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV: n := n.(*ir.AssignListStmt) if len(n.Lhs) < 2 || len(n.Rhs) != 1 { diff --git a/test/fixedbugs/issue68264.go b/test/fixedbugs/issue68264.go new file mode 100644 index 0000000000..7d67e55f6e --- /dev/null +++ b/test/fixedbugs/issue68264.go @@ -0,0 +1,15 @@ +// compile + +// Copyright 2024 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 p + +type nat []int + +var a, b nat = y() + +func y() (nat, []int) { + return nat{0}, nat{1} +} From ad77cefeb2f5b3f1cef4383e974195ffc8610236 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 3 Jul 2024 11:46:46 +0700 Subject: [PATCH 51/72] cmd/compile: correct RewriteMultiValueCall fatal message The function name was changed in CL 331470. Change-Id: I6f41866a9c5ccce594dd84185ebfc1c5af280184 Reviewed-on: https://go-review.googlesource.com/c/go/+/596395 Reviewed-by: Cherry Mui Auto-Submit: Cuong Manh Le LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Than McIntosh --- src/cmd/compile/internal/typecheck/typecheck.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/compile/internal/typecheck/typecheck.go b/src/cmd/compile/internal/typecheck/typecheck.go index b4b9ecd836..ec849e3154 100644 --- a/src/cmd/compile/internal/typecheck/typecheck.go +++ b/src/cmd/compile/internal/typecheck/typecheck.go @@ -663,14 +663,14 @@ func RewriteMultiValueCall(n ir.InitNode, call ir.Node) { switch n := n.(type) { default: - base.Fatalf("rewriteMultiValueCall %+v", n.Op()) + base.Fatalf("RewriteMultiValueCall %+v", n.Op()) case *ir.CallExpr: n.Args = list case *ir.ReturnStmt: n.Results = list case *ir.AssignListStmt: if n.Op() != ir.OAS2FUNC { - base.Fatalf("rewriteMultiValueCall: invalid op %v", n.Op()) + base.Fatalf("RewriteMultiValueCall: invalid op %v", n.Op()) } as.SetOp(ir.OAS2FUNC) n.SetOp(ir.OAS2) From d0146bd85bb6870aa43a498b06ccb473af55cbe3 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Thu, 4 Jul 2024 18:07:45 -0400 Subject: [PATCH 52/72] os/exec: only use cachedLookExtensions if Cmd.Path is unmodified Caching the invocation of lookExtensions on an absolute path in Command and reusing the cached result in Start is only viable if Cmd.Path isn't set to a different value after Command returns. For #66586. Fixes #68314. Change-Id: I57007850aca2011b11344180c00faded737617b5 Reviewed-on: https://go-review.googlesource.com/c/go/+/596875 Reviewed-by: qiu laidongfeng2 <2645477756@qq.com> Reviewed-by: Ian Lance Taylor Auto-Submit: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov --- src/os/exec/exec.go | 65 +++++++++++++++++++++------------------- src/os/exec/exec_test.go | 22 +++++++++++++- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/src/os/exec/exec.go b/src/os/exec/exec.go index 50ed3a8d16..da9f68fe28 100644 --- a/src/os/exec/exec.go +++ b/src/os/exec/exec.go @@ -334,8 +334,10 @@ type Cmd struct { lookPathErr error // cachedLookExtensions caches the result of calling lookExtensions. + // It is set when Command is called with an absolute path, letting it do + // the work of resolving the extension, so Start doesn't need to do it again. // This is only used on Windows. - cachedLookExtensions string + cachedLookExtensions struct{ in, out string } } // A ctxResult reports the result of watching the Context associated with a @@ -436,12 +438,12 @@ func Command(name string, arg ...string) *Cmd { // Since the path is absolute, its extension should be unambiguous // and independent of cmd.Dir, and we can go ahead and cache the lookup now. // - // Note that we cannot add an extension here for relative paths, because - // cmd.Dir may be set after we return from this function and that may cause - // the command to resolve to a different extension. - lp, err := lookExtensions(name, "") - cmd.cachedLookExtensions = lp - if err != nil { + // Note that we don't cache anything here for relative paths, because + // cmd.Dir may be set after we return from this function and that may + // cause the command to resolve to a different extension. + if lp, err := lookExtensions(name, ""); err == nil { + cmd.cachedLookExtensions.in, cmd.cachedLookExtensions.out = name, lp + } else { cmd.Err = err } } @@ -642,29 +644,32 @@ func (c *Cmd) Start() error { return c.Err } lp := c.Path - if c.cachedLookExtensions != "" { - lp = c.cachedLookExtensions - } - if runtime.GOOS == "windows" && c.cachedLookExtensions == "" { - // If c.Path is relative, we had to wait until now - // to resolve it in case c.Dir was changed. - // (If it is absolute, we already resolved its extension in Command - // and shouldn't need to do so again.) - // - // Unfortunately, we cannot write the result back to c.Path because programs - // may assume that they can call Start concurrently with reading the path. - // (It is safe and non-racy to do so on Unix platforms, and users might not - // test with the race detector on all platforms; - // see https://go.dev/issue/62596.) - // - // So we will pass the fully resolved path to os.StartProcess, but leave - // c.Path as is: missing a bit of logging information seems less harmful - // than triggering a surprising data race, and if the user really cares - // about that bit of logging they can always use LookPath to resolve it. - var err error - lp, err = lookExtensions(c.Path, c.Dir) - if err != nil { - return err + if runtime.GOOS == "windows" { + if c.Path == c.cachedLookExtensions.in { + // If Command was called with an absolute path, we already resolved + // its extension and shouldn't need to do so again (provided c.Path + // wasn't set to another value between the calls to Command and Start). + lp = c.cachedLookExtensions.out + } else { + // If *Cmd was made without using Command at all, or if Command was + // called with a relative path, we had to wait until now to resolve + // it in case c.Dir was changed. + // + // Unfortunately, we cannot write the result back to c.Path because programs + // may assume that they can call Start concurrently with reading the path. + // (It is safe and non-racy to do so on Unix platforms, and users might not + // test with the race detector on all platforms; + // see https://go.dev/issue/62596.) + // + // So we will pass the fully resolved path to os.StartProcess, but leave + // c.Path as is: missing a bit of logging information seems less harmful + // than triggering a surprising data race, and if the user really cares + // about that bit of logging they can always use LookPath to resolve it. + var err error + lp, err = lookExtensions(c.Path, c.Dir) + if err != nil { + return err + } } } if c.Cancel != nil && c.ctx == nil { diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go index dbe59fea11..a0bb89e203 100644 --- a/src/os/exec/exec_test.go +++ b/src/os/exec/exec_test.go @@ -1838,7 +1838,7 @@ func TestPathRace(t *testing.T) { func TestAbsPathExec(t *testing.T) { testenv.MustHaveExec(t) - testenv.MustHaveGoBuild(t) // must have GOROOT/bin/gofmt, but close enough + testenv.MustHaveGoBuild(t) // must have GOROOT/bin/{go,gofmt} // A simple exec of a full path should work. // Go 1.22 broke this on Windows, requiring ".exe"; see #66586. @@ -1863,4 +1863,24 @@ func TestAbsPathExec(t *testing.T) { if err == nil { t.Errorf("using exec.Cmd{Path: %#q}: unexpected success", cmd.Path) } + + // A simple exec after modifying Cmd.Path should work. + // This broke on Windows. See go.dev/issue/68314. + t.Run("modified", func(t *testing.T) { + if exec.Command(filepath.Join(testenv.GOROOT(t), "bin/go")).Run() == nil { + // The implementation of the test case below relies on the go binary + // exiting with a non-zero exit code when run without any arguments. + // In the unlikely case that changes, we need to use another binary. + t.Fatal("test case needs updating to verify fix for go.dev/issue/68314") + } + exe1 := filepath.Join(testenv.GOROOT(t), "bin/go") + exe2 := filepath.Join(testenv.GOROOT(t), "bin/gofmt") + cmd := exec.Command(exe1) + cmd.Path = exe2 + cmd.Args = []string{cmd.Path} + err := cmd.Run() + if err != nil { + t.Error("ran wrong binary") + } + }) } From b43d6c57dee2e02a173796c1bc11840de3681dcf Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 24 May 2024 23:41:22 +0700 Subject: [PATCH 53/72] io: add test for Pipe constructor allocations Updates #67633 Change-Id: If3da9317ba36cb8a7868db94b45c402e1793e018 Reviewed-on: https://go-review.googlesource.com/c/go/+/588219 Auto-Submit: Cuong Manh Le Auto-Submit: Ian Lance Taylor Reviewed-by: Mateusz Poliwczak Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/io/pipe_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/io/pipe_test.go b/src/io/pipe_test.go index a8c4e306cc..fcf94d52d2 100644 --- a/src/io/pipe_test.go +++ b/src/io/pipe_test.go @@ -421,3 +421,21 @@ func sortBytesInGroups(b []byte, n int) []byte { slices.SortFunc(groups, bytes.Compare) return bytes.Join(groups, nil) } + +var ( + rSink *PipeReader + wSink *PipeWriter +) + +func TestPipeAllocations(t *testing.T) { + numAllocs := testing.AllocsPerRun(10, func() { + rSink, wSink = Pipe() + }) + + // go.dev/cl/473535 claimed Pipe() should only do 2 allocations, + // plus the 2 escaping to heap for simulating real world usages. + expectedAllocs := 4 + if int(numAllocs) > expectedAllocs { + t.Fatalf("too many allocations for io.Pipe() call: %f", numAllocs) + } +} From 5565462a866af6d882d1f367ae5611260ad07b79 Mon Sep 17 00:00:00 2001 From: qiulaidongfeng <2645477756@qq.com> Date: Sat, 6 Jul 2024 23:03:27 +0000 Subject: [PATCH 54/72] cmd/dist: remove iter,slices,maps test on GOEXPERIMENT=rangefunc In go1.23, don't need use GOEXPERIMENT=rangefunc enable range-over-func. Change-Id: I88b799c4b38c8fbeed8d9f912a0c3c6c45c80e9d GitHub-Last-Rev: 64fd4524f1d2f66049fdce1f68912742c98fb8d9 GitHub-Pull-Request: golang/go#68325 Reviewed-on: https://go-review.googlesource.com/c/go/+/596517 Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Than McIntosh LUCI-TryBot-Result: Go LUCI --- src/cmd/dist/test.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index d7cbadf7b1..0ffcabe416 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -711,19 +711,6 @@ func (t *tester) registerTests() { }) } - // GOEXPERIMENT=rangefunc tests - if !t.compileOnly { - for _, pkg := range []string{"iter", "slices", "maps"} { - t.registerTest("GOEXPERIMENT=rangefunc", - &goTest{ - variant: pkg, - short: t.short, - env: []string{"GOEXPERIMENT=rangefunc"}, - pkg: pkg, - }) - } - } - // GODEBUG=gcstoptheworld=2 tests. We only run these in long-test // mode (with GO_TEST_SHORT=0) because this is just testing a // non-critical debug setting. From 6d89b38ed86e0bfa0ddaba08dc4071e6bb300eea Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 6 Jul 2024 14:42:16 -0700 Subject: [PATCH 55/72] unsafe: clarify when String bytes can be modified They can be modified when the string returned by String no longer exists. Fixes #68300 Change-Id: I526a068151f7aad1ab6827504b51a84e7399cafe Reviewed-on: https://go-review.googlesource.com/c/go/+/596955 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Than McIntosh Commit-Queue: Ian Lance Taylor Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/unsafe/unsafe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unsafe/unsafe.go b/src/unsafe/unsafe.go index 8d6cacb8b5..645ddf2c8a 100644 --- a/src/unsafe/unsafe.go +++ b/src/unsafe/unsafe.go @@ -260,7 +260,7 @@ func SliceData(slice []ArbitraryType) *ArbitraryType // a run-time panic occurs. // // Since Go strings are immutable, the bytes passed to String -// must not be modified afterwards. +// must not be modified as long as the returned string value exists. func String(ptr *byte, len IntegerType) string // StringData returns a pointer to the underlying bytes of str. From 87ec2c959c73e62bfae230ef7efca11ec2a90804 Mon Sep 17 00:00:00 2001 From: Julian Dax Date: Sun, 7 Jul 2024 23:41:02 +0200 Subject: [PATCH 56/72] testing: remove call to os.Exit in documentation for TestMain In the example for the TestMain function, os.Exit was called explicitly, which is no longer necessary since Go 1.15 (see change #219639). Updates #34129 Change-Id: Ia8021de0d5699742adbb7ab6d28b11c841e596dc Reviewed-on: https://go-review.googlesource.com/c/go/+/596977 Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/testing/testing.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testing/testing.go b/src/testing/testing.go index 200fa659b8..526cba39f8 100644 --- a/src/testing/testing.go +++ b/src/testing/testing.go @@ -362,7 +362,7 @@ // // func TestMain(m *testing.M) { // // call flag.Parse() here if TestMain uses flags -// os.Exit(m.Run()) +// m.Run() // } // // TestMain is a low-level primitive and should not be necessary for casual From 73186ba00251b3ed8baaab36e4f5278c7681155b Mon Sep 17 00:00:00 2001 From: Manuel Sabin Date: Fri, 7 Jun 2024 14:50:42 -0400 Subject: [PATCH 57/72] crypto/internal/cryptotest: add common tests for the hash.Hash interface This CL creates the cryptotest package to host a suite of tests for interfaces that are implemented in the crypto package. This CL includes a set of tests for the hash.Hash interface, and calls these tests from the tests of hash.Hash implementations in crypto/. Tests for other interfaces will be included in subsequent CLs. Updates #25309 Change-Id: Ic47086fd7f585e812c8b0d2186c50792c773781e Reviewed-on: https://go-review.googlesource.com/c/go/+/592855 Reviewed-by: Roland Shoemaker Reviewed-by: Carlos Amedee Reviewed-by: Russell Webb Reviewed-by: Filippo Valsorda LUCI-TryBot-Result: Go LUCI Auto-Submit: Roland Shoemaker --- src/crypto/hmac/hmac_test.go | 41 ++---- src/crypto/internal/cryptotest/hash.go | 189 +++++++++++++++++++++++++ src/crypto/md5/md5_test.go | 5 + src/crypto/sha1/sha1_test.go | 5 + src/crypto/sha256/sha256_test.go | 10 ++ src/crypto/sha512/sha512_test.go | 16 +++ src/go/build/deps_test.go | 3 + 7 files changed, 236 insertions(+), 33 deletions(-) create mode 100644 src/crypto/internal/cryptotest/hash.go diff --git a/src/crypto/hmac/hmac_test.go b/src/crypto/hmac/hmac_test.go index 55415abf02..7accad7632 100644 --- a/src/crypto/hmac/hmac_test.go +++ b/src/crypto/hmac/hmac_test.go @@ -5,8 +5,8 @@ package hmac import ( - "bytes" "crypto/internal/boring" + "crypto/internal/cryptotest" "crypto/md5" "crypto/sha1" "crypto/sha256" @@ -621,39 +621,14 @@ func TestEqual(t *testing.T) { } } -func TestWriteAfterSum(t *testing.T) { - h := New(sha1.New, nil) - h.Write([]byte("hello")) - sumHello := h.Sum(nil) +func TestHMACHash(t *testing.T) { + for i, test := range hmacTests { + baseHash := test.hash + key := test.key - h = New(sha1.New, nil) - h.Write([]byte("hello world")) - sumHelloWorld := h.Sum(nil) - - // Test that Sum has no effect on future Sum or Write operations. - // This is a bit unusual as far as usage, but it's allowed - // by the definition of Go hash.Hash, and some clients expect it to work. - h = New(sha1.New, nil) - h.Write([]byte("hello")) - if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) { - t.Fatalf("1st Sum after hello = %x, want %x", sum, sumHello) - } - if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) { - t.Fatalf("2nd Sum after hello = %x, want %x", sum, sumHello) - } - - h.Write([]byte(" world")) - if sum := h.Sum(nil); !bytes.Equal(sum, sumHelloWorld) { - t.Fatalf("1st Sum after hello world = %x, want %x", sum, sumHelloWorld) - } - if sum := h.Sum(nil); !bytes.Equal(sum, sumHelloWorld) { - t.Fatalf("2nd Sum after hello world = %x, want %x", sum, sumHelloWorld) - } - - h.Reset() - h.Write([]byte("hello")) - if sum := h.Sum(nil); !bytes.Equal(sum, sumHello) { - t.Fatalf("Sum after Reset + hello = %x, want %x", sum, sumHello) + t.Run(fmt.Sprintf("test-%d", i), func(t *testing.T) { + cryptotest.TestHash(t, func() hash.Hash { return New(baseHash, key) }) + }) } } diff --git a/src/crypto/internal/cryptotest/hash.go b/src/crypto/internal/cryptotest/hash.go new file mode 100644 index 0000000000..a950dcb282 --- /dev/null +++ b/src/crypto/internal/cryptotest/hash.go @@ -0,0 +1,189 @@ +// Copyright 2024 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 cryptotest + +import ( + "bytes" + "hash" + "io" + "math/rand" + "testing" + "time" +) + +type MakeHash func() hash.Hash + +// TestHash performs a set of tests on hash.Hash implementations, checking the +// documented requirements of Write, Sum, Reset, Size, and BlockSize. +func TestHash(t *testing.T, mh MakeHash) { + + // Test that Sum returns an appended digest matching output of Size + t.Run("SumAppend", func(t *testing.T) { + h := mh() + rng := newRandReader(t) + + emptyBuff := []byte("") + shortBuff := []byte("a") + longBuff := make([]byte, h.BlockSize()+1) + rng.Read(longBuff) + + // Set of example strings to append digest to + prefixes := [][]byte{nil, emptyBuff, shortBuff, longBuff} + + // Go to each string and check digest gets appended to and is correct size. + for _, prefix := range prefixes { + h.Reset() + + sum := getSum(t, h, prefix) // Append new digest to prefix + + // Check that Sum didn't alter the prefix + if !bytes.Equal(sum[0:len(prefix)], prefix) { + t.Errorf("Sum alters passed buffer instead of appending; got %x, want %x", sum[0:len(prefix)], prefix) + } + + // Check that the appended sum wasn't affected by the prefix + if expectedSum := getSum(t, h, nil); !bytes.Equal(sum[len(prefix):], expectedSum) { + t.Errorf("Sum behavior affected by data in the input buffer; got %x, want %x", sum[len(prefix):], expectedSum) + } + + // Check size of append + if got, want := len(sum)-len(prefix), h.Size(); got != want { + t.Errorf("Sum appends number of bytes != Size; got %v , want %v", got, want) + } + } + }) + + // Test that Hash.Write never returns error. + t.Run("WriteWithoutError", func(t *testing.T) { + h := mh() + rng := newRandReader(t) + + emptySlice := []byte("") + shortSlice := []byte("a") + longSlice := make([]byte, h.BlockSize()+1) + rng.Read(longSlice) + + // Set of example strings to append digest to + slices := [][]byte{emptySlice, shortSlice, longSlice} + + for _, slice := range slices { + writeToHash(t, h, slice) // Writes and checks Write doesn't error + } + }) + + t.Run("ResetState", func(t *testing.T) { + h := mh() + rng := newRandReader(t) + + emptySum := getSum(t, h, nil) + + // Write to hash and then Reset it and see if Sum is same as emptySum + writeEx := make([]byte, h.BlockSize()) + rng.Read(writeEx) + writeToHash(t, h, writeEx) + h.Reset() + resetSum := getSum(t, h, nil) + + if !bytes.Equal(emptySum, resetSum) { + t.Errorf("Reset hash yields different Sum than new hash; got %x, want %x", emptySum, resetSum) + } + }) + + // Check that Write isn't reading from beyond input slice's bounds + t.Run("OutOfBoundsRead", func(t *testing.T) { + h := mh() + blockSize := h.BlockSize() + rng := newRandReader(t) + + msg := make([]byte, blockSize) + rng.Read(msg) + writeToHash(t, h, msg) + expectedDigest := getSum(t, h, nil) // Record control digest + + h.Reset() + + // Make a buffer with msg in the middle and data on either end + buff := make([]byte, blockSize*3) + endOfPrefix, startOfSuffix := blockSize, blockSize*2 + + copy(buff[endOfPrefix:startOfSuffix], msg) + rng.Read(buff[:endOfPrefix]) + rng.Read(buff[startOfSuffix:]) + + writeToHash(t, h, buff[endOfPrefix:startOfSuffix]) + testDigest := getSum(t, h, nil) + + if !bytes.Equal(testDigest, expectedDigest) { + t.Errorf("Write affected by data outside of input slice bounds; got %x, want %x", testDigest, expectedDigest) + } + }) + + // Test that multiple calls to Write is stateful + t.Run("StatefulWrite", func(t *testing.T) { + h := mh() + rng := newRandReader(t) + + prefix, suffix := make([]byte, h.BlockSize()), make([]byte, h.BlockSize()) + rng.Read(prefix) + rng.Read(suffix) + + // Write prefix then suffix sequentially and record resulting hash + writeToHash(t, h, prefix) + writeToHash(t, h, suffix) + serialSum := getSum(t, h, nil) + + h.Reset() + + // Write prefix and suffix at the same time and record resulting hash + writeToHash(t, h, append(prefix, suffix...)) + compositeSum := getSum(t, h, nil) + + // Check that sequential writing results in the same as writing all at once + if !bytes.Equal(compositeSum, serialSum) { + t.Errorf("two successive Write calls resulted in a different Sum than a single one; got %x, want %x", compositeSum, serialSum) + } + }) +} + +// Helper function for writing. Verifies that Write does not error. +func writeToHash(t *testing.T, h hash.Hash, p []byte) { + t.Helper() + + before := make([]byte, len(p)) + copy(before, p) + + n, err := h.Write(p) + if err != nil || n != len(p) { + t.Errorf("Write returned error; got (%v, %v), want (nil, %v)", err, n, len(p)) + } + + if !bytes.Equal(p, before) { + t.Errorf("Write modified input slice; got %x, want %x", p, before) + } +} + +// Helper function for getting Sum. Checks that Sum doesn't change hash state. +func getSum(t *testing.T, h hash.Hash, buff []byte) []byte { + t.Helper() + + testBuff := make([]byte, len(buff)) + copy(testBuff, buff) + + sum := h.Sum(buff) + testSum := h.Sum(testBuff) + + // Check that Sum doesn't change underlying hash state + if !bytes.Equal(sum, testSum) { + t.Errorf("successive calls to Sum yield different results; got %x, want %x", sum, testSum) + } + + return sum +} + +func newRandReader(t *testing.T) io.Reader { + seed := time.Now().UnixNano() + t.Logf("Deterministic RNG seed: 0x%x", seed) + return rand.New(rand.NewSource(seed)) +} diff --git a/src/crypto/md5/md5_test.go b/src/crypto/md5/md5_test.go index 851e7fb10d..a5b661126d 100644 --- a/src/crypto/md5/md5_test.go +++ b/src/crypto/md5/md5_test.go @@ -6,6 +6,7 @@ package md5 import ( "bytes" + "crypto/internal/cryptotest" "crypto/rand" "encoding" "fmt" @@ -225,6 +226,10 @@ func TestAllocations(t *testing.T) { } } +func TestMD5Hash(t *testing.T) { + cryptotest.TestHash(t, New) +} + var bench = New() var buf = make([]byte, 1024*1024*8+1) var sum = make([]byte, bench.Size()) diff --git a/src/crypto/sha1/sha1_test.go b/src/crypto/sha1/sha1_test.go index 85ed126091..634ab9de1b 100644 --- a/src/crypto/sha1/sha1_test.go +++ b/src/crypto/sha1/sha1_test.go @@ -9,6 +9,7 @@ package sha1 import ( "bytes" "crypto/internal/boring" + "crypto/internal/cryptotest" "crypto/rand" "encoding" "fmt" @@ -234,6 +235,10 @@ func TestAllocations(t *testing.T) { } } +func TestSHA1Hash(t *testing.T) { + cryptotest.TestHash(t, New) +} + var bench = New() var buf = make([]byte, 8192) diff --git a/src/crypto/sha256/sha256_test.go b/src/crypto/sha256/sha256_test.go index 7304678346..d91f01e9ba 100644 --- a/src/crypto/sha256/sha256_test.go +++ b/src/crypto/sha256/sha256_test.go @@ -9,6 +9,7 @@ package sha256 import ( "bytes" "crypto/internal/boring" + "crypto/internal/cryptotest" "crypto/rand" "encoding" "fmt" @@ -325,6 +326,15 @@ func TestCgo(t *testing.T) { h.Sum(nil) } +func TestSHA256Hash(t *testing.T) { + t.Run("SHA-224", func(t *testing.T) { + cryptotest.TestHash(t, New224) + }) + t.Run("SHA-256", func(t *testing.T) { + cryptotest.TestHash(t, New) + }) +} + var bench = New() var buf = make([]byte, 8192) diff --git a/src/crypto/sha512/sha512_test.go b/src/crypto/sha512/sha512_test.go index 921cdbb7bb..a1ff571383 100644 --- a/src/crypto/sha512/sha512_test.go +++ b/src/crypto/sha512/sha512_test.go @@ -9,6 +9,7 @@ package sha512 import ( "bytes" "crypto/internal/boring" + "crypto/internal/cryptotest" "crypto/rand" "encoding" "encoding/hex" @@ -909,6 +910,21 @@ func TestAllocations(t *testing.T) { } } +func TestSHA512Hash(t *testing.T) { + t.Run("SHA-384", func(t *testing.T) { + cryptotest.TestHash(t, New384) + }) + t.Run("SHA-512/224", func(t *testing.T) { + cryptotest.TestHash(t, New512_224) + }) + t.Run("SHA-512/256", func(t *testing.T) { + cryptotest.TestHash(t, New512_256) + }) + t.Run("SHA-512", func(t *testing.T) { + cryptotest.TestHash(t, New) + }) +} + var bench = New() var buf = make([]byte, 8192) diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 84b0096c77..9146cae492 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -642,6 +642,9 @@ var depsRules = ` FMT < internal/txtar; + CRYPTO-MATH, testing + < crypto/internal/cryptotest; + # v2 execution trace parser. FMT < internal/trace/event; From e89e880eacb1aceaa14733f44c38e6748d5ffa9c Mon Sep 17 00:00:00 2001 From: Clide Stefani Date: Tue, 11 Jun 2024 14:42:13 -0400 Subject: [PATCH 58/72] crypto/tls: add support for -reject-alpn and -decline-alpn flags to bogo_shim_test The existing implementation of bogo_shim_test does not support tests which use the reject-alpn or the decline-alpn flag. This change adds support for these flags in bogo_shim_test. Updates #51434 Updates #46310 Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest Change-Id: I3ff23ff4edd8f4c6c37ee6c9f2ee4689066c4e00 Reviewed-on: https://go-review.googlesource.com/c/go/+/592198 Reviewed-by: Roland Shoemaker Reviewed-by: David Chase Auto-Submit: Roland Shoemaker LUCI-TryBot-Result: Go LUCI --- src/crypto/tls/bogo_shim_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/crypto/tls/bogo_shim_test.go b/src/crypto/tls/bogo_shim_test.go index 2d8100d1bb..38087d2b1c 100644 --- a/src/crypto/tls/bogo_shim_test.go +++ b/src/crypto/tls/bogo_shim_test.go @@ -75,6 +75,8 @@ var ( advertiseALPN = flag.String("advertise-alpn", "", "") expectALPN = flag.String("expect-alpn", "", "") + rejectALPN = flag.Bool("reject-alpn", false, "") + declineALPN = flag.Bool("decline-alpn", false, "") hostName = flag.String("host-name", "", "") @@ -126,6 +128,14 @@ func bogoShim() { } } + if *rejectALPN { + cfg.NextProtos = []string{"unnegotiableprotocol"} + } + + if *declineALPN { + cfg.NextProtos = []string{} + } + if *hostName != "" { cfg.ServerName = *hostName } @@ -256,6 +266,9 @@ func bogoShim() { if *expectVersion != 0 && cs.Version != uint16(*expectVersion) { log.Fatalf("expected ssl version %q, got %q", uint16(*expectVersion), cs.Version) } + if *declineALPN && cs.NegotiatedProtocol != "" { + log.Fatal("unexpected ALPN protocol") + } if *expectECHAccepted && !cs.ECHAccepted { log.Fatal("expected ECH to be accepted, but connection state shows it was not") } else if i == 0 && *onInitialExpectECHAccepted && !cs.ECHAccepted { From 183a40db6def2780478053b3cd14f3f5c355d999 Mon Sep 17 00:00:00 2001 From: Nick Ripley Date: Tue, 2 Jul 2024 12:53:36 -0400 Subject: [PATCH 59/72] runtime: avoid multiple records with identical stacks from MutexProfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using frame pointer unwinding, we defer frame skipping and inline expansion for call stacks until profile reporting time. We can end up with records which have different stacks if no frames are skipped, but identical stacks once skipping is taken into account. Returning multiple records with the same stack (but different values) has broken programs which rely on the records already being fully aggregated by call stack when returned from runtime.MutexProfile. This CL addresses the problem by handling skipping at recording time. We do full inline expansion to correctly skip the desired number of frames when recording the call stack, and then handle the rest of inline expansion when reporting the profile. The regression test in this CL is adapted from the reproducer in https://github.com/grafana/pyroscope-go/issues/103, authored by Tolya Korniltsev. Fixes #67548 Co-Authored-By: Tolya Korniltsev Change-Id: I6a42ce612377f235b2c8c0cec9ba8e9331224b84 Reviewed-on: https://go-review.googlesource.com/c/go/+/595966 LUCI-TryBot-Result: Go LUCI Reviewed-by: Carlos Amedee Reviewed-by: Cherry Mui Auto-Submit: Carlos Amedee Reviewed-by: Felix Geisendörfer --- src/runtime/mprof.go | 105 ++++++++++++++++++++++++++++---- src/runtime/pprof/pprof.go | 23 ++++++- src/runtime/pprof/pprof_test.go | 78 ++++++++++++++++++++++++ 3 files changed, 192 insertions(+), 14 deletions(-) diff --git a/src/runtime/mprof.go b/src/runtime/mprof.go index b4fe0e5549..e5620aec11 100644 --- a/src/runtime/mprof.go +++ b/src/runtime/mprof.go @@ -9,6 +9,7 @@ package runtime import ( "internal/abi" + "internal/goarch" "internal/profilerecord" "internal/runtime/atomic" "runtime/internal/sys" @@ -542,16 +543,14 @@ func saveblockevent(cycles, rate int64, skip int, which bucketType) { gp := getg() mp := acquirem() // we must not be preempted while accessing profstack - nstk := 1 + var nstk int if tracefpunwindoff() || gp.m.hasCgoOnStack() { - mp.profStack[0] = logicalStackSentinel if gp.m.curg == nil || gp.m.curg == gp { - nstk = callers(skip, mp.profStack[1:]) + nstk = callers(skip, mp.profStack) } else { - nstk = gcallers(gp.m.curg, skip, mp.profStack[1:]) + nstk = gcallers(gp.m.curg, skip, mp.profStack) } } else { - mp.profStack[0] = uintptr(skip) if gp.m.curg == nil || gp.m.curg == gp { if skip > 0 { // We skip one fewer frame than the provided value for frame @@ -559,12 +558,12 @@ func saveblockevent(cycles, rate int64, skip int, which bucketType) { // frame, whereas the saved frame pointer will give us the // caller's return address first (so, not including // saveblockevent) - mp.profStack[0] -= 1 + skip -= 1 } - nstk += fpTracebackPCs(unsafe.Pointer(getfp()), mp.profStack[1:]) + nstk = fpTracebackPartialExpand(skip, unsafe.Pointer(getfp()), mp.profStack) } else { - mp.profStack[1] = gp.m.curg.sched.pc - nstk += 1 + fpTracebackPCs(unsafe.Pointer(gp.m.curg.sched.bp), mp.profStack[2:]) + mp.profStack[0] = gp.m.curg.sched.pc + nstk = 1 + fpTracebackPartialExpand(skip, unsafe.Pointer(gp.m.curg.sched.bp), mp.profStack[1:]) } } @@ -572,6 +571,52 @@ func saveblockevent(cycles, rate int64, skip int, which bucketType) { releasem(mp) } +// fpTracebackPartialExpand records a call stack obtained starting from fp. +// This function will skip the given number of frames, properly accounting for +// inlining, and save remaining frames as "physical" return addresses. The +// consumer should later use CallersFrames or similar to expand inline frames. +func fpTracebackPartialExpand(skip int, fp unsafe.Pointer, pcBuf []uintptr) int { + var n int + lastFuncID := abi.FuncIDNormal + skipOrAdd := func(retPC uintptr) bool { + if skip > 0 { + skip-- + } else if n < len(pcBuf) { + pcBuf[n] = retPC + n++ + } + return n < len(pcBuf) + } + for n < len(pcBuf) && fp != nil { + // return addr sits one word above the frame pointer + pc := *(*uintptr)(unsafe.Pointer(uintptr(fp) + goarch.PtrSize)) + + if skip > 0 { + callPC := pc - 1 + fi := findfunc(callPC) + u, uf := newInlineUnwinder(fi, callPC) + for ; uf.valid(); uf = u.next(uf) { + sf := u.srcFunc(uf) + if sf.funcID == abi.FuncIDWrapper && elideWrapperCalling(lastFuncID) { + // ignore wrappers + } else if more := skipOrAdd(uf.pc + 1); !more { + return n + } + lastFuncID = sf.funcID + } + } else { + // We've skipped the desired number of frames, so no need + // to perform further inline expansion now. + pcBuf[n] = pc + n++ + } + + // follow the frame pointer to the next one + fp = unsafe.Pointer(*(*uintptr)(fp)) + } + return n +} + // lockTimer assists with profiling contention on runtime-internal locks. // // There are several steps between the time that an M experiences contention and @@ -1075,10 +1120,34 @@ type BlockProfileRecord struct { // the [testing] package's -test.blockprofile flag instead // of calling BlockProfile directly. func BlockProfile(p []BlockProfileRecord) (n int, ok bool) { - return blockProfileInternal(len(p), func(r profilerecord.BlockProfileRecord) { + n, ok = blockProfileInternal(len(p), func(r profilerecord.BlockProfileRecord) { copyBlockProfileRecord(&p[0], r) p = p[1:] }) + if !ok { + return + } + expandFrames(p[:n]) + return +} + +func expandFrames(p []BlockProfileRecord) { + expandedStack := makeProfStack() + for i := range p { + cf := CallersFrames(p[i].Stack()) + j := 0 + for ; j < len(expandedStack); j++ { + f, more := cf.Next() + // f.PC is a "call PC", but later consumers will expect + // "return PCs" + expandedStack[i] = f.PC + 1 + if !more { + break + } + } + k := copy(p[i].Stack0[:], expandedStack[:j]) + clear(p[i].Stack0[k:]) + } } // blockProfileInternal returns the number of records n in the profile. If there @@ -1111,6 +1180,9 @@ func blockProfileInternal(size int, copyFn func(profilerecord.BlockProfileRecord return } +// copyBlockProfileRecord copies the sample values and call stack from src to dst. +// The call stack is copied as-is. The caller is responsible for handling inline +// expansion, needed when the call stack was collected with frame pointer unwinding. func copyBlockProfileRecord(dst *BlockProfileRecord, src profilerecord.BlockProfileRecord) { dst.Count = src.Count dst.Cycles = src.Cycles @@ -1123,7 +1195,11 @@ func copyBlockProfileRecord(dst *BlockProfileRecord, src profilerecord.BlockProf if asanenabled { asanwrite(unsafe.Pointer(&dst.Stack0[0]), unsafe.Sizeof(dst.Stack0)) } - i := fpunwindExpand(dst.Stack0[:], src.Stack) + // We just copy the stack here without inline expansion + // (needed if frame pointer unwinding is used) + // since this function is called under the profile lock, + // and doing something that might allocate can violate lock ordering. + i := copy(dst.Stack0[:], src.Stack) clear(dst.Stack0[i:]) } @@ -1142,10 +1218,15 @@ func pprof_blockProfileInternal(p []profilerecord.BlockProfileRecord) (n int, ok // Most clients should use the [runtime/pprof] package // instead of calling MutexProfile directly. func MutexProfile(p []BlockProfileRecord) (n int, ok bool) { - return mutexProfileInternal(len(p), func(r profilerecord.BlockProfileRecord) { + n, ok = mutexProfileInternal(len(p), func(r profilerecord.BlockProfileRecord) { copyBlockProfileRecord(&p[0], r) p = p[1:] }) + if !ok { + return + } + expandFrames(p[:n]) + return } // mutexProfileInternal returns the number of records n in the profile. If there diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index d3af5bba91..4b7a9f63c6 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -404,6 +404,25 @@ type countProfile interface { Label(i int) *labelMap } +// expandInlinedFrames copies the call stack from pcs into dst, expanding any +// PCs corresponding to inlined calls into the corresponding PCs for the inlined +// functions. Returns the number of frames copied to dst. +func expandInlinedFrames(dst, pcs []uintptr) int { + cf := runtime.CallersFrames(pcs) + var n int + for n < len(dst) { + f, more := cf.Next() + // f.PC is a "call PC", but later consumers will expect + // "return PCs" + dst[n] = f.PC + 1 + n++ + if !more { + break + } + } + return n +} + // printCountCycleProfile outputs block profile records (for block or mutex profiles) // as the pprof-proto format output. Translations from cycle count to time duration // are done because The proto expects count and time (nanoseconds) instead of count @@ -426,7 +445,7 @@ func printCountCycleProfile(w io.Writer, countName, cycleName string, records [] values[1] = int64(float64(r.Cycles) / cpuGHz) // For count profiles, all stack addresses are // return PCs, which is what appendLocsForStack expects. - n := pprof_fpunwindExpand(expandedStack[:], r.Stack) + n := expandInlinedFrames(expandedStack, r.Stack) locs = b.appendLocsForStack(locs[:0], expandedStack[:n]) b.pbSample(values, locs, nil) } @@ -935,7 +954,7 @@ func writeProfileInternal(w io.Writer, debug int, name string, runtimeProfile fu for i := range p { r := &p[i] fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count) - n := pprof_fpunwindExpand(expandedStack, r.Stack) + n := expandInlinedFrames(expandedStack, r.Stack) stack := expandedStack[:n] for _, pc := range stack { fmt.Fprintf(w, " %#x", pc) diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go index 09abbb31ae..bd11914544 100644 --- a/src/runtime/pprof/pprof_test.go +++ b/src/runtime/pprof/pprof_test.go @@ -2578,3 +2578,81 @@ func produceProfileEvents(t *testing.T, depth int) { runtime.GC() goroutineDeep(t, depth-4) // -4 for produceProfileEvents, **, chanrecv1, chanrev, gopark } + +func TestMutexBlockFullAggregation(t *testing.T) { + // This regression test is adapted from + // https://github.com/grafana/pyroscope-go/issues/103, + // authored by Tolya Korniltsev + + var m sync.Mutex + + prev := runtime.SetMutexProfileFraction(-1) + defer runtime.SetMutexProfileFraction(prev) + + const fraction = 1 + const iters = 100 + const workers = 2 + + runtime.SetMutexProfileFraction(fraction) + runtime.SetBlockProfileRate(1) + defer runtime.SetBlockProfileRate(0) + + wg := sync.WaitGroup{} + wg.Add(workers) + for j := 0; j < workers; j++ { + go func() { + for i := 0; i < iters; i++ { + m.Lock() + // Wait at least 1 millisecond to pass the + // starvation threshold for the mutex + time.Sleep(time.Millisecond) + m.Unlock() + } + wg.Done() + }() + } + wg.Wait() + + assertNoDuplicates := func(name string, collect func([]runtime.BlockProfileRecord) (int, bool)) { + var p []runtime.BlockProfileRecord + n, ok := collect(nil) + for { + p = make([]runtime.BlockProfileRecord, n+50) + n, ok = collect(p) + if ok { + p = p[:n] + break + } + } + seen := make(map[string]struct{}) + for _, r := range p { + cf := runtime.CallersFrames(r.Stack()) + var stack strings.Builder + for { + f, more := cf.Next() + stack.WriteString(f.Func.Name()) + if !more { + break + } + stack.WriteByte('\n') + } + s := stack.String() + if !strings.Contains(s, "TestMutexBlockFullAggregation") { + continue + } + if _, ok := seen[s]; ok { + t.Errorf("saw duplicate entry in %s profile with stack:\n%s", name, s) + } + seen[s] = struct{}{} + } + if len(seen) == 0 { + t.Errorf("did not see any samples in %s profile for this test", name) + } + } + t.Run("mutex", func(t *testing.T) { + assertNoDuplicates("mutex", runtime.MutexProfile) + }) + t.Run("block", func(t *testing.T) { + assertNoDuplicates("block", runtime.BlockProfile) + }) +} From 70e453b4361b80a85e6ebb37e4d43ec02db9a50a Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Tue, 9 Jul 2024 20:24:34 +0100 Subject: [PATCH 60/72] context: handle nil values for valueCtx.String() Fixes #68356 Change-Id: I57dc089a99f545e29a6759a8db5e28fabb6d1a61 Reviewed-on: https://go-review.googlesource.com/c/go/+/597415 Commit-Queue: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Joseph Tsai Reviewed-by: Damien Neil Auto-Submit: Ian Lance Taylor --- src/context/context.go | 2 ++ src/context/x_test.go | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/context/context.go b/src/context/context.go index 30adfe987d..763d4f777f 100644 --- a/src/context/context.go +++ b/src/context/context.go @@ -739,6 +739,8 @@ func stringify(v any) string { return s.String() case string: return s + case nil: + return "" } return reflectlite.TypeOf(v).String() } diff --git a/src/context/x_test.go b/src/context/x_test.go index 2c66ed42b2..ab3c2757cf 100644 --- a/src/context/x_test.go +++ b/src/context/x_test.go @@ -243,6 +243,10 @@ func TestValues(t *testing.T) { c4 := WithValue(c3, k1, nil) check(c4, "c4", "", "c2k2", "c3k3") + if got, want := fmt.Sprint(c4), `context.Background.WithValue(context_test.key1, c1k1).WithValue(context_test.key2(1), c2k2).WithValue(context_test.key2(3), c3k3).WithValue(context_test.key1, )`; got != want { + t.Errorf("c.String() = %q want %q", got, want) + } + o0 := otherContext{Background()} check(o0, "o0", "", "", "") From b3040679ad0eccaaadb825ed8c0704086ecc23eb Mon Sep 17 00:00:00 2001 From: Jorropo Date: Sat, 6 Jul 2024 04:48:04 +0200 Subject: [PATCH 61/72] math: remove riscv64 assembly implementations of rounding Fixes #68322 This reverts commit ad377e906a8ee6f27545d83de280206dacec1e58. Change-Id: Ifa4811e2c679d789cc830dbff5e50301410e24d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/596516 Reviewed-by: Than McIntosh Reviewed-by: Keith Randall Commit-Queue: Cuong Manh Le Auto-Submit: Cuong Manh Le Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Reviewed-by: Cuong Manh Le --- src/math/floor_asm.go | 2 +- src/math/floor_noasm.go | 2 +- src/math/floor_riscv64.s | 41 ------------------------------------ test/fixedbugs/issue68322.go | 17 +++++++++++++++ 4 files changed, 19 insertions(+), 43 deletions(-) delete mode 100644 src/math/floor_riscv64.s create mode 100644 test/fixedbugs/issue68322.go diff --git a/src/math/floor_asm.go b/src/math/floor_asm.go index 5cb45f5a7e..fb419d6da2 100644 --- a/src/math/floor_asm.go +++ b/src/math/floor_asm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build 386 || amd64 || arm64 || ppc64 || ppc64le || riscv64 || s390x || wasm +//go:build 386 || amd64 || arm64 || ppc64 || ppc64le || s390x || wasm package math diff --git a/src/math/floor_noasm.go b/src/math/floor_noasm.go index 6754ca8fc8..5641c7ea0a 100644 --- a/src/math/floor_noasm.go +++ b/src/math/floor_noasm.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !386 && !amd64 && !arm64 && !ppc64 && !ppc64le && !riscv64 && !s390x && !wasm +//go:build !386 && !amd64 && !arm64 && !ppc64 && !ppc64le && !s390x && !wasm package math diff --git a/src/math/floor_riscv64.s b/src/math/floor_riscv64.s deleted file mode 100644 index 62ce963781..0000000000 --- a/src/math/floor_riscv64.s +++ /dev/null @@ -1,41 +0,0 @@ -// 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. - -#include "textflag.h" - -#define PosInf 0x7FF0000000000000 - -// The rounding mode of RISC-V is different from Go spec. - -#define ROUNDFN(NAME, MODE) \ -TEXT NAME(SB),NOSPLIT,$0; \ - MOVD x+0(FP), F0; \ - /* whether x is NaN */; \ - FEQD F0, F0, X6; \ - BNEZ X6, 3(PC); \ - /* return NaN if x is NaN */; \ - MOVD F0, ret+8(FP); \ - RET; \ - MOV $PosInf, X6; \ - FMVDX X6, F1; \ - FABSD F0, F2; \ - /* if abs(x) > +Inf, return Inf instead of round(x) */; \ - FLTD F1, F2, X6; \ - /* Inf should keep same signed with x then return */; \ - BEQZ X6, 3(PC); \ - FCVTLD.MODE F0, X6; \ - FCVTDL X6, F1; \ - /* rounding will drop signed bit in RISCV, restore it */; \ - FSGNJD F0, F1, F0; \ - MOVD F0, ret+8(FP); \ - RET - -// func archFloor(x float64) float64 -ROUNDFN(·archFloor, RDN) - -// func archCeil(x float64) float64 -ROUNDFN(·archCeil, RUP) - -// func archTrunc(x float64) float64 -ROUNDFN(·archTrunc, RTZ) diff --git a/test/fixedbugs/issue68322.go b/test/fixedbugs/issue68322.go new file mode 100644 index 0000000000..9b3e713d59 --- /dev/null +++ b/test/fixedbugs/issue68322.go @@ -0,0 +1,17 @@ +// run + +// Copyright 2024 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 main + +import "math" + +var doNotFold = 18446744073709549568.0 + +func main() { + if math.Trunc(doNotFold) != doNotFold { + panic("big (over 2**63-1) math.Trunc is incorrect") + } +} From 5881d857c573874bde9417e97df3267f19c7ecb6 Mon Sep 17 00:00:00 2001 From: Clide Stefani Date: Tue, 25 Jun 2024 11:46:39 -0400 Subject: [PATCH 62/72] crypto/tls: add support for -expect-no-hrr to bogo_shim_test The existing implementation of bogo_shim_test does not support tests that use the expect-no-hrr flag. This change adds support for this flag. Updates #51434 Change-Id: Iadb38fc2262783cab144a7b52904d0443e7fc2c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/594835 LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker Reviewed-by: Russell Webb Reviewed-by: Carlos Amedee Auto-Submit: Roland Shoemaker --- src/crypto/tls/bogo_shim_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/crypto/tls/bogo_shim_test.go b/src/crypto/tls/bogo_shim_test.go index 38087d2b1c..f481a5a40f 100644 --- a/src/crypto/tls/bogo_shim_test.go +++ b/src/crypto/tls/bogo_shim_test.go @@ -54,6 +54,7 @@ var ( echConfigListB64 = flag.String("ech-config-list", "", "") expectECHAccepted = flag.Bool("expect-ech-accept", false, "") expectHRR = flag.Bool("expect-hrr", false, "") + expectNoHRR = flag.Bool("expect-no-hrr", false, "") expectedECHRetryConfigs = flag.String("expect-ech-retry-configs", "", "") expectNoECHRetryConfigs = flag.Bool("expect-no-ech-retry-configs", false, "") onInitialExpectECHAccepted = flag.Bool("on-initial-expect-ech-accept", false, "") @@ -283,6 +284,10 @@ func bogoShim() { log.Fatal("expected HRR but did not do it") } + if *expectNoHRR && cs.testingOnlyDidHRR { + log.Fatal("expected no HRR but did do it") + } + if *expectSessionMiss && cs.DidResume { log.Fatal("unexpected session resumption") } From dfaaa91f0537f806a02ff2dd71b79844cd16cc4e Mon Sep 17 00:00:00 2001 From: Diogo Pinela Date: Thu, 28 Mar 2019 20:35:28 +0000 Subject: [PATCH 63/72] os: clarify that IsNotExist, IsExist, IsPermission and IsTimeout work with nil errors Referring to these functions' parameter as "*the* error" could be taken to imply that a non-nil error from elsewhere is expected; referring to it as "its argument" avoids that ambiguity. Fixes #31065 Change-Id: I117892dd53fff6f92d11a416e4abedee5d2f9337 Reviewed-on: https://go-review.googlesource.com/c/go/+/170077 Reviewed-by: Rob Pike Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Jonathan Amsterdam --- src/os/error.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/os/error.go b/src/os/error.go index 5a824a9e0e..284b9e992c 100644 --- a/src/os/error.go +++ b/src/os/error.go @@ -71,7 +71,7 @@ func NewSyscallError(syscall string, err error) error { return &SyscallError{syscall, err} } -// IsExist returns a boolean indicating whether the error is known to report +// IsExist returns a boolean indicating whether its argument is known to report // that a file or directory already exists. It is satisfied by [ErrExist] as // well as some syscall errors. // @@ -81,7 +81,7 @@ func IsExist(err error) bool { return underlyingErrorIs(err, ErrExist) } -// IsNotExist returns a boolean indicating whether the error is known to +// IsNotExist returns a boolean indicating whether its argument is known to // report that a file or directory does not exist. It is satisfied by // [ErrNotExist] as well as some syscall errors. // @@ -91,7 +91,7 @@ func IsNotExist(err error) bool { return underlyingErrorIs(err, ErrNotExist) } -// IsPermission returns a boolean indicating whether the error is known to +// IsPermission returns a boolean indicating whether its argument is known to // report that permission is denied. It is satisfied by [ErrPermission] as well // as some syscall errors. // @@ -101,7 +101,7 @@ func IsPermission(err error) bool { return underlyingErrorIs(err, ErrPermission) } -// IsTimeout returns a boolean indicating whether the error is known +// IsTimeout returns a boolean indicating whether its argument is known // to report that a timeout occurred. // // This function predates [errors.Is], and the notion of whether an From 08a6e080cae0277f0c5458da84c7e3ca4d8f8199 Mon Sep 17 00:00:00 2001 From: Jonathan Hall Date: Wed, 10 Jan 2024 21:23:25 +0100 Subject: [PATCH 64/72] database/sql/driver: fix name in comment DefaultValueConverter => DefaultParameterConverter Change-Id: I0e726cfdbf21a5e00928899d1fd9144f89dcb805 Reviewed-on: https://go-review.googlesource.com/c/go/+/555235 Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Shay Nehmad Reviewed-by: Carlos Amedee Auto-Submit: Ian Lance Taylor --- src/database/sql/driver/driver.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/database/sql/driver/driver.go b/src/database/sql/driver/driver.go index da310bfb12..d0892e80fc 100644 --- a/src/database/sql/driver/driver.go +++ b/src/database/sql/driver/driver.go @@ -415,7 +415,7 @@ type NamedValueChecker interface { type ColumnConverter interface { // ColumnConverter returns a ValueConverter for the provided // column index. If the type of a specific column isn't known - // or shouldn't be handled specially, DefaultValueConverter + // or shouldn't be handled specially, [DefaultParameterConverter] // can be returned. ColumnConverter(idx int) ValueConverter } From 611f18c4e9c63921f6e036a4738542f476b7305a Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 10 Jul 2024 18:37:00 -0700 Subject: [PATCH 65/72] strings: more cross-references in docstrings This amends CL 534775. Change-Id: I25a217da51853ec29106998e19e9386d756902fc Reviewed-on: https://go-review.googlesource.com/c/go/+/597655 LUCI-TryBot-Result: Go LUCI Reviewed-by: Carlos Amedee Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- src/strings/compare.go | 2 +- src/strings/replace.go | 2 +- src/strings/strings.go | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/strings/compare.go b/src/strings/compare.go index b3c01fddc1..dcf442471a 100644 --- a/src/strings/compare.go +++ b/src/strings/compare.go @@ -10,7 +10,7 @@ import "internal/bytealg" // The result will be 0 if a == b, -1 if a < b, and +1 if a > b. // // Use Compare when you need to perform a three-way comparison (with -// slices.SortFunc, for example). It is usually clearer and always faster +// [slices.SortFunc], for example). It is usually clearer and always faster // to use the built-in string comparison operators ==, <, >, and so on. func Compare(a, b string) int { return bytealg.CompareString(a, b) diff --git a/src/strings/replace.go b/src/strings/replace.go index 3b17a55b91..ae12728800 100644 --- a/src/strings/replace.go +++ b/src/strings/replace.go @@ -299,7 +299,7 @@ func makeGenericReplacer(oldnew []string) *genericReplacer { type appendSliceWriter []byte -// Write writes to the buffer to satisfy io.Writer. +// Write writes to the buffer to satisfy [io.Writer]. func (w *appendSliceWriter) Write(p []byte) (int, error) { *w = append(*w, p...) return len(p), nil diff --git a/src/strings/strings.go b/src/strings/strings.go index 95180828f6..fba303c12a 100644 --- a/src/strings/strings.go +++ b/src/strings/strings.go @@ -121,7 +121,7 @@ func IndexByte(s string, c byte) int { // IndexRune returns the index of the first instance of the Unicode code point // r, or -1 if rune is not present in s. -// If r is utf8.RuneError, it returns the first instance of any +// If r is [utf8.RuneError], it returns the first instance of any // invalid UTF-8 byte sequence. func IndexRune(s string, r rune) int { switch { @@ -275,7 +275,7 @@ func genSplit(s, sep string, sepSave, n int) []string { // Edge cases for s and sep (for example, empty strings) are handled // as described in the documentation for [Split]. // -// To split around the first instance of a separator, see Cut. +// To split around the first instance of a separator, see [Cut]. func SplitN(s, sep string, n int) []string { return genSplit(s, sep, 0, n) } // SplitAfterN slices s into substrings after each instance of sep and @@ -304,7 +304,7 @@ func SplitAfterN(s, sep string, n int) []string { // // It is equivalent to [SplitN] with a count of -1. // -// To split around the first instance of a separator, see Cut. +// To split around the first instance of a separator, see [Cut]. func Split(s, sep string) []string { return genSplit(s, sep, 0, -1) } // SplitAfter slices s into all substrings after each instance of sep and @@ -324,7 +324,7 @@ func SplitAfter(s, sep string) []string { var asciiSpace = [256]uint8{'\t': 1, '\n': 1, '\v': 1, '\f': 1, '\r': 1, ' ': 1} // Fields splits the string s around each instance of one or more consecutive white space -// characters, as defined by unicode.IsSpace, returning a slice of substrings of s or an +// characters, as defined by [unicode.IsSpace], returning a slice of substrings of s or an // empty slice if s contains only white space. func Fields(s string) []string { // First count the fields. From a71bb570d064f6d0c1cf59cef4b7a044be7a39d3 Mon Sep 17 00:00:00 2001 From: cuishuang Date: Thu, 4 Jul 2024 14:10:55 +0800 Subject: [PATCH 66/72] all: make struct comments match struct names Change-Id: I011f66854a9af5f3baa20abebd4b315c15db571f Reviewed-on: https://go-review.googlesource.com/c/go/+/596715 Reviewed-by: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov TryBot-Result: Gopher Robot Run-TryBot: shuang cui Auto-Submit: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Commit-Queue: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/cmd/trace/gstate.go | 2 +- src/internal/coverage/defs.go | 2 +- src/log/slog/internal/buffer/buffer.go | 5 ++++- src/runtime/arena.go | 2 +- src/sync/export_test.go | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cmd/trace/gstate.go b/src/cmd/trace/gstate.go index bcbe3b6c7f..638d492670 100644 --- a/src/cmd/trace/gstate.go +++ b/src/cmd/trace/gstate.go @@ -46,7 +46,7 @@ type gState[R resource] struct { // goroutine stopped executing. These are flushed on every stop or block. completedRanges []completedRange - // startRunning is the most recent event that caused a goroutine to + // startRunningTime is the most recent event that caused a goroutine to // transition to GoRunning. startRunningTime trace.Time diff --git a/src/internal/coverage/defs.go b/src/internal/coverage/defs.go index 340ac95635..1ef47638e6 100644 --- a/src/internal/coverage/defs.go +++ b/src/internal/coverage/defs.go @@ -267,7 +267,7 @@ func (cm CounterGranularity) String() string { // by the Go command and by the coverage runtime. const MetaFilesFileName = "metafiles.txt" -// MetaFilePaths contains information generated by the Go command and +// MetaFileCollection contains information generated by the Go command and // the read in by coverage test support functions within an executing // "go test -cover" binary. type MetaFileCollection struct { diff --git a/src/log/slog/internal/buffer/buffer.go b/src/log/slog/internal/buffer/buffer.go index 310ec37d4a..110c6281ab 100644 --- a/src/log/slog/internal/buffer/buffer.go +++ b/src/log/slog/internal/buffer/buffer.go @@ -7,7 +7,10 @@ package buffer import "sync" -// buffer adapted from go/src/fmt/print.go +// Buffer is a byte buffer. +// +// This implementation is adapted from the unexported type buffer +// in go/src/fmt/print.go. type Buffer []byte // Having an initial size gives a dramatic speedup. diff --git a/src/runtime/arena.go b/src/runtime/arena.go index 47b131466c..cd9a9dfae1 100644 --- a/src/runtime/arena.go +++ b/src/runtime/arena.go @@ -232,7 +232,7 @@ func userArenaChunkReserveBytes() uintptr { } type userArena struct { - // full is a list of full chunks that have not enough free memory left, and + // fullList is a list of full chunks that have not enough free memory left, and // that we'll free once this user arena is freed. // // Can't use mSpanList here because it's not-in-heap. diff --git a/src/sync/export_test.go b/src/sync/export_test.go index b55cecd987..ddde30e018 100644 --- a/src/sync/export_test.go +++ b/src/sync/export_test.go @@ -10,7 +10,7 @@ var Runtime_Semrelease = runtime_Semrelease var Runtime_procPin = runtime_procPin var Runtime_procUnpin = runtime_procUnpin -// poolDequeue testing. +// PoolDequeue exports an interface for pollDequeue testing. type PoolDequeue interface { PushHead(val any) bool PopHead() (any, bool) From b31e9a63a4d7ed98b89719ee54b752920782ae15 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 6 Jul 2024 14:09:26 -0700 Subject: [PATCH 67/72] unsafe: say "functions like syscall.Syscall", not only Syscall Fixes #68301 Change-Id: I9d7f623370705ab2ad4c49489b5a89162467f22a Reviewed-on: https://go-review.googlesource.com/c/go/+/596936 Commit-Queue: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor Reviewed-by: Keith Randall Auto-Submit: Ian Lance Taylor --- src/unsafe/unsafe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unsafe/unsafe.go b/src/unsafe/unsafe.go index 645ddf2c8a..de9421bab5 100644 --- a/src/unsafe/unsafe.go +++ b/src/unsafe/unsafe.go @@ -110,7 +110,7 @@ type IntegerType int // u := unsafe.Pointer(nil) // p := unsafe.Pointer(uintptr(u) + offset) // -// (4) Conversion of a Pointer to a uintptr when calling [syscall.Syscall]. +// (4) Conversion of a Pointer to a uintptr when calling functions like [syscall.Syscall]. // // The Syscall functions in package syscall pass their uintptr arguments directly // to the operating system, which then may, depending on the details of the call, From 8bc32ab6b11a4428f8f0d0eec8db02d520ce422f Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 10 Jul 2024 23:20:11 +1000 Subject: [PATCH 68/72] os: clean up after TestIssue60181 This test currently leaves two temp files lying around - ensure these are created in the current working directory (a temp dir) so that they get cleaned up when the test is complete. Change-Id: I9a29e24a2cd601de3ab39c421830ee2bcda76516 Reviewed-on: https://go-review.googlesource.com/c/go/+/597317 LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- src/os/os_unix_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 6cbeae1b78..fcc75e5ee6 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -376,14 +376,14 @@ func TestIssue60181(t *testing.T) { want := "hello gopher" - a, err := CreateTemp("", "a") + a, err := CreateTemp(".", "a") if err != nil { t.Fatal(err) } a.WriteString(want[:5]) a.Close() - b, err := CreateTemp("", "b") + b, err := CreateTemp(".", "b") if err != nil { t.Fatal(err) } From 4e77872d16340595d76b905fe24369b76cfd1b5f Mon Sep 17 00:00:00 2001 From: Tim King Date: Tue, 9 Jul 2024 14:01:56 -0700 Subject: [PATCH 69/72] go/types: fix assertion failure when range over int is not permitted Fixes an assertion failure in Checker.rangeStmt that range over int only has a key type and no value type. When allowVersion failed, rangeKeyVal returns Typ[Invalid] for the value instead of nil. When Config.Error != nil, rangeStmt proceeded. The check for rhs[1]==nil was not enough to catch this case. It must also check rhs[1]== Updates #68334 Change-Id: Iffa1b2f7b6a94570ec50b8c6603e727a45ba3357 Reviewed-on: https://go-review.googlesource.com/c/go/+/597356 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- .../compile/internal/types2/issues_test.go | 29 +++++++++++++++++++ src/cmd/compile/internal/types2/stmt.go | 9 +++--- src/go/types/issues_test.go | 29 +++++++++++++++++++ src/go/types/stmt.go | 9 +++--- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index b4da3c0b91..20e3f52fac 100644 --- a/src/cmd/compile/internal/types2/issues_test.go +++ b/src/cmd/compile/internal/types2/issues_test.go @@ -1092,3 +1092,32 @@ func _() { conf := Config{GoVersion: "go1.17"} mustTypecheck(src, &conf, nil) } + +func TestIssue68334(t *testing.T) { + const src = ` +package p + +func f(x int) { + for i, j := range x { + _, _ = i, j + } + var a, b int + for a, b = range x { + _, _ = a, b + } +} +` + + got := "" + conf := Config{ + GoVersion: "go1.21", // #68334 requires GoVersion <= 1.21 + Error: func(err error) { got += err.Error() + "\n" }, // #68334 requires Error != nil + } + typecheck(src, &conf, nil) // do not crash + + want := "p:5:20: cannot range over x (variable of type int): requires go1.22 or later\n" + + "p:9:19: cannot range over x (variable of type int): requires go1.22 or later\n" + if got != want { + t.Errorf("got: %s want: %s", got, want) + } +} diff --git a/src/cmd/compile/internal/types2/stmt.go b/src/cmd/compile/internal/types2/stmt.go index 58783f47c3..b598a4f068 100644 --- a/src/cmd/compile/internal/types2/stmt.go +++ b/src/cmd/compile/internal/types2/stmt.go @@ -920,14 +920,15 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s // initialize lhs iteration variable, if any typ := rhs[i] - if typ == nil { + if typ == nil || typ == Typ[Invalid] { + // typ == Typ[Invalid] can happen if allowVersion fails. obj.typ = Typ[Invalid] obj.used = true // don't complain about unused variable continue } if rangeOverInt { - assert(i == 0) // at most one iteration variable (rhs[1] == nil for rangeOverInt) + assert(i == 0) // at most one iteration variable (rhs[1] == nil or Typ[Invalid] for rangeOverInt) check.initVar(obj, &x, "range clause") } else { var y operand @@ -957,12 +958,12 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s // assign to lhs iteration variable, if any typ := rhs[i] - if typ == nil { + if typ == nil || typ == Typ[Invalid] { continue } if rangeOverInt { - assert(i == 0) // at most one iteration variable (rhs[1] == nil for rangeOverInt) + assert(i == 0) // at most one iteration variable (rhs[1] == nil or Typ[Invalid] for rangeOverInt) check.assignVar(lhs, nil, &x, "range clause") // If the assignment succeeded, if x was untyped before, it now // has a type inferred via the assignment. It must be an integer. diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index c99c9a9550..3f459d3883 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -1102,3 +1102,32 @@ func _() { conf := Config{GoVersion: "go1.17"} mustTypecheck(src, &conf, nil) } + +func TestIssue68334(t *testing.T) { + const src = ` +package p + +func f(x int) { + for i, j := range x { + _, _ = i, j + } + var a, b int + for a, b = range x { + _, _ = a, b + } +} +` + + got := "" + conf := Config{ + GoVersion: "go1.21", // #68334 requires GoVersion <= 1.21 + Error: func(err error) { got += err.Error() + "\n" }, // #68334 requires Error != nil + } + typecheck(src, &conf, nil) // do not crash + + want := "p:5:20: cannot range over x (variable of type int): requires go1.22 or later\n" + + "p:9:19: cannot range over x (variable of type int): requires go1.22 or later\n" + if got != want { + t.Errorf("got: %s want: %s", got, want) + } +} diff --git a/src/go/types/stmt.go b/src/go/types/stmt.go index 215b20160d..c9f7a4f929 100644 --- a/src/go/types/stmt.go +++ b/src/go/types/stmt.go @@ -922,14 +922,15 @@ func (check *Checker) rangeStmt(inner stmtContext, s *ast.RangeStmt) { // initialize lhs iteration variable, if any typ := rhs[i] - if typ == nil { + if typ == nil || typ == Typ[Invalid] { + // typ == Typ[Invalid] can happen if allowVersion fails. obj.typ = Typ[Invalid] obj.used = true // don't complain about unused variable continue } if rangeOverInt { - assert(i == 0) // at most one iteration variable (rhs[1] == nil for rangeOverInt) + assert(i == 0) // at most one iteration variable (rhs[1] == nil or Typ[Invalid] for rangeOverInt) check.initVar(obj, &x, "range clause") } else { var y operand @@ -959,12 +960,12 @@ func (check *Checker) rangeStmt(inner stmtContext, s *ast.RangeStmt) { // assign to lhs iteration variable, if any typ := rhs[i] - if typ == nil { + if typ == nil || typ == Typ[Invalid] { continue } if rangeOverInt { - assert(i == 0) // at most one iteration variable (rhs[1] == nil for rangeOverInt) + assert(i == 0) // at most one iteration variable (rhs[1] == nil or Typ[Invalid] for rangeOverInt) check.assignVar(lhs, nil, &x, "range clause") // If the assignment succeeded, if x was untyped before, it now // has a type inferred via the assignment. It must be an integer. From 071b8d51c1a70fa6b12f0bed2e93370e193333fd Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Fri, 12 Jul 2024 22:03:43 +0000 Subject: [PATCH 70/72] cmd: vendor golang.org/x/telemetry@268b4a8ec2d7 Commands run, from cmd: go get golang.org/x/telemetry@268b4a8ec2d7 go mod tidy go mod vendor Commands run, from std (to keep versions consistent): go get golang.org/x/sys@v0.22.0 go mod tidy go mod vendor Fixes #67617 Change-Id: I65e759c9b03443619a2a7acbeba53694ff5bbf6a Reviewed-on: https://go-review.googlesource.com/c/go/+/597896 Reviewed-by: Dmitri Shuralyov Auto-Submit: Robert Findley Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI --- src/cmd/go.mod | 6 +- src/cmd/go.sum | 12 +- .../vendor/golang.org/x/mod/module/module.go | 2 - .../vendor/golang.org/x/mod/sumdb/client.go | 8 + .../golang.org/x/mod/sumdb/tlog/tlog.go | 12 +- .../vendor/golang.org/x/sys/unix/mremap.go | 5 + .../golang.org/x/sys/unix/syscall_darwin.go | 12 ++ .../golang.org/x/sys/unix/syscall_unix.go | 9 + .../x/sys/unix/zsyscall_darwin_amd64.go | 33 ++++ .../x/sys/unix/zsyscall_darwin_amd64.s | 10 ++ .../x/sys/unix/zsyscall_darwin_arm64.go | 33 ++++ .../x/sys/unix/zsyscall_darwin_arm64.s | 10 ++ .../x/sys/windows/security_windows.go | 24 ++- .../x/sys/windows/zsyscall_windows.go | 9 + .../golang.org/x/telemetry/counter/doc.go | 7 + .../x/telemetry/internal/counter/counter.go | 50 +++++- .../x/telemetry/internal/counter/file.go | 164 ++++++++++++++---- .../x/telemetry/internal/mmap/mmap.go | 7 +- .../x/telemetry/internal/mmap/mmap_other.go | 8 +- .../x/telemetry/internal/mmap/mmap_unix.go | 14 +- .../x/telemetry/internal/mmap/mmap_windows.go | 22 +-- .../x/telemetry/internal/telemetry/types.go | 4 +- .../x/telemetry/internal/upload/findwork.go | 2 +- .../x/telemetry/internal/upload/reports.go | 7 +- .../x/telemetry/internal/upload/upload.go | 14 +- src/cmd/vendor/modules.txt | 6 +- src/go.mod | 2 +- src/go.sum | 4 +- src/vendor/modules.txt | 2 +- 29 files changed, 400 insertions(+), 98 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 3058165dbf..f568996fd0 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -6,10 +6,10 @@ require ( github.com/google/pprof v0.0.0-20240528025155-186aa0362fba golang.org/x/arch v0.8.0 golang.org/x/build v0.0.0-20240603162849-5dfbda438323 - golang.org/x/mod v0.18.0 + golang.org/x/mod v0.19.0 golang.org/x/sync v0.7.0 - golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 + golang.org/x/sys v0.22.0 + golang.org/x/telemetry v0.0.0-20240712210958-268b4a8ec2d7 golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 081ced64dc..f822fa372a 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -10,14 +10,14 @@ golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/build v0.0.0-20240603162849-5dfbda438323 h1:XHj9DzsjpryRW9MnyZq85mQ1dRpSxVC+2TLcMzVZNMo= golang.org/x/build v0.0.0-20240603162849-5dfbda438323/go.mod h1:yz9anu0Z63yrVrqnoOxoJuyBRDwtGUoOFJwtfvs+D+U= -golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 h1:fzUVo05u80jHc31RGqQsPYEAGMXS8tyK5azYUK2sSms= -golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240712210958-268b4a8ec2d7 h1:nU8/tAV/21mkPrCjACUeSibjhynTovgRMXc32+Y1Aec= +golang.org/x/telemetry v0.0.0-20240712210958-268b4a8ec2d7/go.mod h1:amNmu/SBSm2GAF3X+9U2C0epLocdh+r5Z+7oMYO5cLM= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/mod/module/module.go b/src/cmd/vendor/golang.org/x/mod/module/module.go index cac1a899e9..2a364b229b 100644 --- a/src/cmd/vendor/golang.org/x/mod/module/module.go +++ b/src/cmd/vendor/golang.org/x/mod/module/module.go @@ -506,7 +506,6 @@ var badWindowsNames = []string{ "PRN", "AUX", "NUL", - "COM0", "COM1", "COM2", "COM3", @@ -516,7 +515,6 @@ var badWindowsNames = []string{ "COM7", "COM8", "COM9", - "LPT0", "LPT1", "LPT2", "LPT3", diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/client.go b/src/cmd/vendor/golang.org/x/mod/sumdb/client.go index 04c6e24d0e..04dbdfe46a 100644 --- a/src/cmd/vendor/golang.org/x/mod/sumdb/client.go +++ b/src/cmd/vendor/golang.org/x/mod/sumdb/client.go @@ -142,6 +142,14 @@ func (c *Client) initWork() { c.verifiers = note.VerifierList(verifier) c.name = verifier.Name() + if c.latest.N == 0 { + c.latest.Hash, err = tlog.TreeHash(0, nil) + if err != nil { + c.initErr = err + return + } + } + data, err := c.ops.ReadConfig(c.name + "/latest") if err != nil { c.initErr = err diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go b/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go index 6a11a752f9..f7ea753832 100644 --- a/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go +++ b/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go @@ -234,14 +234,22 @@ func (f HashReaderFunc) ReadHashes(indexes []int64) ([]Hash, error) { return f(indexes) } +// emptyHash is the hash of the empty tree, per RFC 6962, Section 2.1. +// It is the hash of the empty string. +var emptyHash = Hash{ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, +} + // TreeHash computes the hash for the root of the tree with n records, // using the HashReader to obtain previously stored hashes // (those returned by StoredHashes during the writes of those n records). // TreeHash makes a single call to ReadHash requesting at most 1 + log₂ n hashes. -// The tree of size zero is defined to have an all-zero Hash. func TreeHash(n int64, r HashReader) (Hash, error) { if n == 0 { - return Hash{}, nil + return emptyHash, nil } indexes := subTreeIndex(0, n, nil) hashes, err := r.ReadHashes(indexes) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mremap.go b/src/cmd/vendor/golang.org/x/sys/unix/mremap.go index fd45fe529d..3a5e776f89 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/mremap.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/mremap.go @@ -50,3 +50,8 @@ func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data [ func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) { return mapper.Mremap(oldData, newLength, flags) } + +func MremapPtr(oldAddr unsafe.Pointer, oldSize uintptr, newAddr unsafe.Pointer, newSize uintptr, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mremap(uintptr(oldAddr), oldSize, newSize, flags, uintptr(newAddr)) + return unsafe.Pointer(xaddr), err +} diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go index 59542a897d..4cc7b00596 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -542,6 +542,18 @@ func SysctlKinfoProcSlice(name string, args ...int) ([]KinfoProc, error) { } } +//sys pthread_chdir_np(path string) (err error) + +func PthreadChdir(path string) (err error) { + return pthread_chdir_np(path) +} + +//sys pthread_fchdir_np(fd int) (err error) + +func PthreadFchdir(fd int) (err error) { + return pthread_fchdir_np(fd) +} + //sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) //sys shmat(id int, addr uintptr, flag int) (ret uintptr, err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go index 77081de8c7..4e92e5aa40 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_unix.go @@ -154,6 +154,15 @@ func Munmap(b []byte) (err error) { return mapper.Munmap(b) } +func MmapPtr(fd int, offset int64, addr unsafe.Pointer, length uintptr, prot int, flags int) (ret unsafe.Pointer, err error) { + xaddr, err := mapper.mmap(uintptr(addr), length, prot, flags, fd, offset) + return unsafe.Pointer(xaddr), err +} + +func MunmapPtr(addr unsafe.Pointer, length uintptr) (err error) { + return mapper.munmap(uintptr(addr), length) +} + func Read(fd int, p []byte) (n int, err error) { n, err = read(fd, p) if raceenabled { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go index ccb02f240a..07642c308d 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go @@ -760,6 +760,39 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s index 8b8bb28402..923e08cb79 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s @@ -228,6 +228,16 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go index 1b40b997b5..7d73dda647 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go @@ -760,6 +760,39 @@ var libc_sysctl_trampoline_addr uintptr // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func pthread_chdir_np(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + _, _, e1 := syscall_syscall(libc_pthread_chdir_np_trampoline_addr, uintptr(unsafe.Pointer(_p0)), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_chdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_chdir_np pthread_chdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pthread_fchdir_np(fd int) (err error) { + _, _, e1 := syscall_syscall(libc_pthread_fchdir_np_trampoline_addr, uintptr(fd), 0, 0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +var libc_pthread_fchdir_np_trampoline_addr uintptr + +//go:cgo_import_dynamic libc_pthread_fchdir_np pthread_fchdir_np "/usr/lib/libSystem.B.dylib" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) { _, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags)) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s index 08362c1ab7..057700111e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s @@ -228,6 +228,16 @@ TEXT libc_sysctl_trampoline<>(SB),NOSPLIT,$0-0 GLOBL ·libc_sysctl_trampoline_addr(SB), RODATA, $8 DATA ·libc_sysctl_trampoline_addr(SB)/8, $libc_sysctl_trampoline<>(SB) +TEXT libc_pthread_chdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_chdir_np(SB) +GLOBL ·libc_pthread_chdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_chdir_np_trampoline_addr(SB)/8, $libc_pthread_chdir_np_trampoline<>(SB) + +TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0 + JMP libc_pthread_fchdir_np(SB) +GLOBL ·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8 +DATA ·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB) + TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0 JMP libc_sendfile(SB) GLOBL ·libc_sendfile_trampoline_addr(SB), RODATA, $8 diff --git a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go index 6f7d2ac70a..97651b5bd0 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/security_windows.go @@ -894,7 +894,7 @@ type ACL struct { aclRevision byte sbz1 byte aclSize uint16 - aceCount uint16 + AceCount uint16 sbz2 uint16 } @@ -1087,6 +1087,27 @@ type EXPLICIT_ACCESS struct { Trustee TRUSTEE } +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header +type ACE_HEADER struct { + AceType uint8 + AceFlags uint8 + AceSize uint16 +} + +// https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-access_allowed_ace +type ACCESS_ALLOWED_ACE struct { + Header ACE_HEADER + Mask ACCESS_MASK + SidStart uint32 +} + +const ( + // Constants for AceType + // https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-ace_header + ACCESS_ALLOWED_ACE_TYPE = 0 + ACCESS_DENIED_ACE_TYPE = 1 +) + // This type is the union inside of TRUSTEE and must be created using one of the TrusteeValueFrom* functions. type TrusteeValue uintptr @@ -1158,6 +1179,7 @@ type OBJECTS_AND_NAME struct { //sys makeSelfRelativeSD(absoluteSD *SECURITY_DESCRIPTOR, selfRelativeSD *SECURITY_DESCRIPTOR, selfRelativeSDSize *uint32) (err error) = advapi32.MakeSelfRelativeSD //sys setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCESS, oldACL *ACL, newACL **ACL) (ret error) = advapi32.SetEntriesInAclW +//sys GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (ret error) = advapi32.GetAce // Control returns the security descriptor control bits. func (sd *SECURITY_DESCRIPTOR) Control() (control SECURITY_DESCRIPTOR_CONTROL, revision uint32, err error) { diff --git a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go index 9f73df75b5..eba761018a 100644 --- a/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go +++ b/src/cmd/vendor/golang.org/x/sys/windows/zsyscall_windows.go @@ -91,6 +91,7 @@ var ( procEnumServicesStatusExW = modadvapi32.NewProc("EnumServicesStatusExW") procEqualSid = modadvapi32.NewProc("EqualSid") procFreeSid = modadvapi32.NewProc("FreeSid") + procGetAce = modadvapi32.NewProc("GetAce") procGetLengthSid = modadvapi32.NewProc("GetLengthSid") procGetNamedSecurityInfoW = modadvapi32.NewProc("GetNamedSecurityInfoW") procGetSecurityDescriptorControl = modadvapi32.NewProc("GetSecurityDescriptorControl") @@ -1224,6 +1225,14 @@ func setEntriesInAcl(countExplicitEntries uint32, explicitEntries *EXPLICIT_ACCE return } +func GetAce(acl *ACL, aceIndex uint32, pAce **ACCESS_ALLOWED_ACE) (ret error) { + r0, _, _ := syscall.Syscall(procGetAce.Addr(), 3, uintptr(unsafe.Pointer(acl)), uintptr(aceIndex), uintptr(unsafe.Pointer(pAce))) + if r0 == 0 { + ret = GetLastError() + } + return +} + func SetKernelObjectSecurity(handle Handle, securityInformation SECURITY_INFORMATION, securityDescriptor *SECURITY_DESCRIPTOR) (err error) { r1, _, e1 := syscall.Syscall(procSetKernelObjectSecurity.Addr(), 3, uintptr(handle), uintptr(securityInformation), uintptr(unsafe.Pointer(securityDescriptor))) if r1 == 0 { diff --git a/src/cmd/vendor/golang.org/x/telemetry/counter/doc.go b/src/cmd/vendor/golang.org/x/telemetry/counter/doc.go index 53695ac270..639e9ea356 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/counter/doc.go +++ b/src/cmd/vendor/golang.org/x/telemetry/counter/doc.go @@ -48,4 +48,11 @@ // For example given two counters "gopls/completion/latency:<50ms" and // "gopls/completion/latency:<100ms", the "<100ms" bucket counts events // with latency in the half-open interval [50ms, 100ms). +// +// # Debugging +// +// The GODEBUG environment variable can enable printing of additional debug +// information for counters. Adding GODEBUG=countertrace=1 to the environment +// of a process using counters causes the x/telemetry/counter package to log +// counter information to stderr. package counter diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/counter.go b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/counter.go index cc562bc744..6fbcec3a92 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/counter.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/counter.go @@ -15,10 +15,15 @@ import ( "sync/atomic" ) -// Note: not using internal/godebug, so that internal/godebug can use internal/counter. -var debugCounter = strings.Contains(os.Getenv("GODEBUG"), "countertrace=1") +var ( + // Note: not using internal/godebug, so that internal/godebug can use + // internal/counter. + debugCounter = strings.Contains(os.Getenv("GODEBUG"), "countertrace=1") + CrashOnBugs = false // for testing; if set, exit on fatal log messages +) -func debugPrintf(format string, args ...interface{}) { +// debugPrintf formats a debug message if GODEBUG=countertrace=1. +func debugPrintf(format string, args ...any) { if debugCounter { if len(format) == 0 || format[len(format)-1] != '\n' { format += "\n" @@ -27,6 +32,17 @@ func debugPrintf(format string, args ...interface{}) { } } +// debugFatalf logs a fatal error if GODEBUG=countertrace=1. +func debugFatalf(format string, args ...any) { + if debugCounter || CrashOnBugs { + if len(format) == 0 || format[len(format)-1] != '\n' { + format += "\n" + } + fmt.Fprintf(os.Stderr, "counter bug: "+format, args...) + os.Exit(1) + } +} + // A Counter is a single named event counter. // A Counter is safe for use by multiple goroutines simultaneously. // @@ -246,6 +262,7 @@ func (c *Counter) releaseLock(state counterStateBits) { } } +// add wraps the atomic.Uint64.Add operation to handle integer overflow. func (c *Counter) add(n uint64) uint64 { count := c.ptr.count for { @@ -336,11 +353,11 @@ func readFile(f *file) (*File, error) { } // ReadFile reads the counters and stack counters from the given file. -// This is the implementation of x/telemetry/counter/countertest.Read +// This is the implementation of x/telemetry/counter/countertest.ReadFile. func ReadFile(name string) (counters, stackCounters map[string]uint64, _ error) { // TODO: Document the format of the stackCounters names. - data, err := os.ReadFile(name) + data, err := ReadMapped(name) if err != nil { return nil, nil, fmt.Errorf("failed to read from file: %v", err) } @@ -359,3 +376,26 @@ func ReadFile(name string) (counters, stackCounters map[string]uint64, _ error) } return counters, stackCounters, nil } + +// ReadMapped reads the contents of the given file by memory mapping. +// +// This avoids file synchronization issues. +func ReadMapped(name string) ([]byte, error) { + f, err := os.OpenFile(name, os.O_RDWR, 0666) + if err != nil { + return nil, err + } + defer f.Close() + fi, err := f.Stat() + if err != nil { + return nil, err + } + mapping, err := memmap(f) + if err != nil { + return nil, err + } + data := make([]byte, fi.Size()) + copy(data, mapping.Data) + munmap(mapping) + return data, nil +} diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go index e3c574dcb4..4fe9e577b1 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -36,7 +36,22 @@ type file struct { buildInfo *debug.BuildInfo timeBegin, timeEnd time.Time err error - current atomic.Pointer[mappedFile] // may be read without holding mu, but may be nil + // current holds the current file mapping, which may change when the file is + // rotated or extended. + // + // current may be read without holding mu, but may be nil. + // + // The cleanup logic for file mappings is complicated, because invalidating + // counter pointers is reentrant: [file.invalidateCounters] may call + // [file.lookup], which acquires mu. Therefore, writing current must be done + // as follows: + // 1. record the previous value of current + // 2. Store a new value in current + // 3. unlock mu + // 4. call invalidateCounters + // 5. close the previous mapped value from (1) + // TODO(rfindley): simplify + current atomic.Pointer[mappedFile] } var defaultFile file @@ -292,7 +307,7 @@ func (f *file) rotate1() time.Time { } name := filepath.Join(dir, baseName) - m, err := openMapped(name, meta, nil) + m, err := openMapped(name, meta) if err != nil { // Mapping failed: // If there used to be a mapped file, after cleanup @@ -334,8 +349,10 @@ func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { cleanup = nop if newM != nil { f.current.Store(newM) - // TODO(rfindley): shouldn't this close f.current? - cleanup = f.invalidateCounters + cleanup = func() { + f.invalidateCounters() + current.close() + } } return v, cleanup } @@ -374,7 +391,38 @@ func Open() func() { return close } +const ( + FileVersion = "v1" + hdrPrefix = "# telemetry/counter file " + FileVersion + "\n" + recordUnit = 32 + maxMetaLen = 512 + numHash = 512 // 2kB for hash table + maxNameLen = 4 * 1024 + limitOff = 0 + hashOff = 4 + pageSize = 16 * 1024 + minFileLen = 16 * 1024 +) + // A mappedFile is a counter file mmapped into memory. +// +// The file layout for a mappedFile m is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, hdrLen: header, containing metadata; see [mappedHeader] +// hdrLen+limitOff, 4: uint32 allocation limit (byte offset of the end of counter records) +// hdrLen+hashOff, 4*numHash: hash table, stores uint32 heads of a linked list of records, keyed by name hash +// hdrLen+hashOff+4*numHash to limit: counter records: see record syntax below +// +// The record layout is as follows: +// +// offset, byte size: description +// ------------------ ----------- +// 0, 8: uint64 counter value +// 8, 12: uint32 name length +// 12, 16: uint32 offset of next record in linked list +// 16, name length: counter name type mappedFile struct { meta string hdrLen uint32 @@ -384,9 +432,16 @@ type mappedFile struct { mapping *mmap.Data } +// openMapped opens and memory maps a file. +// +// name is the path to the file. +// +// meta is the file metadata, which must match the metadata of the file on disk +// exactly. +// // existing should be nil the first time this is called for a file, // and when remapping, should be the previous mappedFile. -func openMapped(name string, meta string, existing *mappedFile) (_ *mappedFile, err error) { +func openMapped(name, meta string) (_ *mappedFile, err error) { hdr, err := mappedHeader(meta) if err != nil { return nil, err @@ -402,13 +457,13 @@ func openMapped(name string, meta string, existing *mappedFile) (_ *mappedFile, f: f, meta: meta, } - // without this files cannot be cleanedup on Windows (affects tests) - runtime.SetFinalizer(m, (*mappedFile).close) + defer func() { if err != nil { m.close() } }() + info, err := f.Stat() if err != nil { return nil, err @@ -433,17 +488,14 @@ func openMapped(name string, meta string, existing *mappedFile) (_ *mappedFile, } // Map into memory. - var mapping mmap.Data - if existing != nil { - mapping, err = memmap(f, existing.mapping) - } else { - mapping, err = memmap(f, nil) - } + mapping, err := memmap(f) if err != nil { return nil, err } - m.mapping = &mapping + m.mapping = mapping if !bytes.HasPrefix(m.mapping.Data, hdr) { + // TODO(rfindley): we can and should do better here, reading the mapped + // header length and comparing headers exactly. return nil, fmt.Errorf("counter: header mismatch") } m.hdrLen = uint32(len(hdr)) @@ -451,19 +503,6 @@ func openMapped(name string, meta string, existing *mappedFile) (_ *mappedFile, return m, nil } -const ( - FileVersion = "v1" - hdrPrefix = "# telemetry/counter file " + FileVersion + "\n" - recordUnit = 32 - maxMetaLen = 512 - numHash = 512 // 2kB for hash table - maxNameLen = 4 * 1024 - limitOff = 0 - hashOff = 4 - pageSize = 16 * 1024 - minFileLen = 16 * 1024 -) - func mappedHeader(meta string) ([]byte, error) { if len(meta) > maxMetaLen { return nil, fmt.Errorf("counter: metadata too large") @@ -484,6 +523,11 @@ func (m *mappedFile) place(limit uint32, name string) (start, end uint32) { } n := round(uint32(16+len(name)), recordUnit) start = round(limit, recordUnit) // should already be rounded but just in case + // Note: Checking for crossing a page boundary would be + // start/pageSize != (start+n-1)/pageSize, + // but we are checking for reaching the page end, so no -1. + // The page end is reserved for use by extend. + // See the comment in m.extend. if start/pageSize != (start+n)/pageSize { // bump start to next page start = round(limit, pageSize) @@ -538,6 +582,9 @@ func (m *mappedFile) cas32(off, old, new uint32) bool { return (*atomic.Uint32)(unsafe.Pointer(&m.mapping.Data[off])).CompareAndSwap(old, new) } +// entryAt reads a counter record at the given byte offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. func (m *mappedFile) entryAt(off uint32) (name []byte, next uint32, v *atomic.Uint64, ok bool) { if off < m.hdrLen+hashOff || int64(off)+16 > int64(len(m.mapping.Data)) { return nil, 0, nil, false @@ -552,7 +599,14 @@ func (m *mappedFile) entryAt(off uint32) (name []byte, next uint32, v *atomic.Ui return name, next, v, true } +// writeEntryAt writes a new counter record at the given offset. +// +// See the documentation for [mappedFile] for a description of the counter record layout. +// +// writeEntryAt only returns false in the presence of some form of corruption: +// an offset outside the bounds of the record region in the mapped file. func (m *mappedFile) writeEntryAt(off uint32, name string) (next *atomic.Uint32, v *atomic.Uint64, ok bool) { + // TODO(rfindley): shouldn't this first condition be off < m.hdrLen+hashOff+4*numHash? if off < m.hdrLen+hashOff || int64(off)+16+int64(len(name)) > int64(len(m.mapping.Data)) { return nil, nil, false } @@ -563,6 +617,11 @@ func (m *mappedFile) writeEntryAt(off uint32, name string) (next *atomic.Uint32, return next, v, true } +// lookup searches the mapped file for a counter record with the given name, returning: +// - v: the mapped counter value +// - headOff: the offset of the head pointer (see [mappedFile]) +// - head: the value of the head pointer +// - ok: whether lookup succeeded func (m *mappedFile) lookup(name string) (v *atomic.Uint64, headOff, head uint32, ok bool) { h := hash(name) headOff = m.hdrLen + hashOff + h*4 @@ -581,6 +640,9 @@ func (m *mappedFile) lookup(name string) (v *atomic.Uint64, headOff, head uint32 return nil, headOff, head, true } +// newCounter allocates and writes a new counter record with the given name. +// +// If name is already recorded in the file, newCounter returns the existing counter. func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, err error) { if len(name) > maxNameLen { return nil, nil, fmt.Errorf("counter name too long") @@ -597,19 +659,37 @@ func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, }() v, headOff, head, ok := m.lookup(name) - for !ok { + for tries := 0; !ok; tries++ { + if tries >= 10 { + debugFatalf("corrupt: failed to remap after 10 tries") + return nil, nil, errCorrupt + } // Lookup found an invalid pointer, // perhaps because the file has grown larger than the mapping. limit := m.load32(m.hdrLen + limitOff) - if int64(limit) <= int64(len(m.mapping.Data)) { - // Mapping doesn't need to grow, so lookup found actual corruption. - debugPrintf("corrupt1\n") + if limit, datalen := int64(limit), int64(len(m.mapping.Data)); limit <= datalen { + // Mapping doesn't need to grow, so lookup found actual corruption, + // in the form of an entry pointer that exceeds the recorded allocation + // limit. This should never happen, unless the actual file contents are + // corrupt. + debugFatalf("corrupt: limit %d is within mapping length %d", limit, datalen) return nil, nil, errCorrupt } - newM, err := openMapped(m.f.Name(), m.meta, m) + // That the recorded limit is greater than the mapped data indicates that + // an external process has extended the file. Re-map to pick up this extension. + newM, err := openMapped(m.f.Name(), m.meta) if err != nil { return nil, nil, err } + if limit, datalen := int64(limit), int64(len(newM.mapping.Data)); limit > datalen { + // We've re-mapped, yet limit still exceeds the data length. This + // indicates that the underlying file was somehow truncated, or the + // recorded limit is corrupt. + debugFatalf("corrupt: limit %d exceeds file size %d", limit, datalen) + return nil, nil, errCorrupt + } + // If m != orig, this is at least the second time around the loop + // trying to open the mapping. Close the previous attempt. if m != orig { m.close() } @@ -650,7 +730,7 @@ func (m *mappedFile) newCounter(name string) (v *atomic.Uint64, m1 *mappedFile, // Write record. next, v, ok := m.writeEntryAt(start, name) if !ok { - debugPrintf("corrupt2 %#x+%d vs %#x\n", start, len(name), len(m.mapping.Data)) + debugFatalf("corrupt: failed to write entry: %#x+%d vs %#x\n", start, len(name), len(m.mapping.Data)) return nil, nil, errCorrupt // more likely our math is wrong } @@ -686,12 +766,26 @@ func (m *mappedFile) extend(end uint32) (*mappedFile, error) { return nil, err } if info.Size() < int64(end) { + // Note: multiple processes could be calling extend at the same time, + // but this write only writes the last 4 bytes of the page. + // The last 4 bytes of the page are reserved for this purpose and hold no data. + // (In m.place, if a new record would extend to the very end of the page, + // it is placed in the next page instead.) + // So it is fine if multiple processes extend at the same time. if _, err := m.f.WriteAt(m.zero[:], int64(end)-int64(len(m.zero))); err != nil { return nil, err } } - newM, err := openMapped(m.f.Name(), m.meta, m) - m.f.Close() + newM, err := openMapped(m.f.Name(), m.meta) + if err != nil { + return nil, err + } + if int64(len(newM.mapping.Data)) < int64(end) { + // File system or logic bug: new file is somehow not extended. + // See go.dev/issue/68311, where this appears to have been happening. + newM.close() + return nil, errCorrupt + } return newM, err } diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap.go b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap.go index fb3ca9650d..2febe3ecb9 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap.go @@ -26,12 +26,11 @@ type Data struct { // Mmap maps the given file into memory. // When remapping a file, pass the most recently returned Data. -func Mmap(f *os.File, data *Data) (Data, error) { - return mmapFile(f, data) +func Mmap(f *os.File) (*Data, error) { + return mmapFile(f) } // Munmap unmaps the given file from memory. func Munmap(d *Data) error { - // d.f.Close() on Windows still gets an error - return munmapFile(*d) + return munmapFile(d) } diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go index 361ca8b01a..190afd8e9f 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_other.go @@ -12,14 +12,14 @@ import ( ) // mmapFile on other systems doesn't mmap the file. It just reads everything. -func mmapFile(f *os.File, _ *Data) (Data, error) { +func mmapFile(f *os.File) (*Data, error) { b, err := io.ReadAll(f) if err != nil { - return Data{}, err + return nil, err } - return Data{f, b, nil}, nil + return &Data{f, b, nil}, nil } -func munmapFile(d Data) error { +func munmapFile(_ *Data) error { return nil } diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go index af462ff676..f15ac615b3 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_unix.go @@ -13,29 +13,29 @@ import ( "syscall" ) -func mmapFile(f *os.File, _ *Data) (Data, error) { +func mmapFile(f *os.File) (*Data, error) { st, err := f.Stat() if err != nil { - return Data{}, err + return nil, err } size := st.Size() pagesize := int64(os.Getpagesize()) if int64(int(size+(pagesize-1))) != size+(pagesize-1) { - return Data{}, fmt.Errorf("%s: too large for mmap", f.Name()) + return nil, fmt.Errorf("%s: too large for mmap", f.Name()) } n := int(size) if n == 0 { - return Data{f, nil, nil}, nil + return &Data{f, nil, nil}, nil } mmapLength := int(((size + pagesize - 1) / pagesize) * pagesize) // round up to page size data, err := syscall.Mmap(int(f.Fd()), 0, mmapLength, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) if err != nil { - return Data{}, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} + return nil, &fs.PathError{Op: "mmap", Path: f.Name(), Err: err} } - return Data{f, data[:n], nil}, nil + return &Data{f, data[:n], nil}, nil } -func munmapFile(d Data) error { +func munmapFile(d *Data) error { if len(d.Data) == 0 { return nil } diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go index e70e7c7b07..2e8dfbea9c 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/mmap/mmap_windows.go @@ -13,35 +13,35 @@ import ( "golang.org/x/sys/windows" ) -func mmapFile(f *os.File, previous *Data) (Data, error) { - if previous != nil { - munmapFile(*previous) - } +func mmapFile(f *os.File) (*Data, error) { st, err := f.Stat() if err != nil { - return Data{}, err + return nil, err } size := st.Size() if size == 0 { - return Data{f, nil, nil}, nil + return &Data{f, nil, nil}, nil } // set the min and max sizes to zero to map the whole file, as described in // https://learn.microsoft.com/en-us/windows/win32/memory/creating-a-file-mapping-object#file-mapping-size h, err := windows.CreateFileMapping(windows.Handle(f.Fd()), nil, syscall.PAGE_READWRITE, 0, 0, nil) if err != nil { - return Data{}, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) + return nil, fmt.Errorf("CreateFileMapping %s: %w", f.Name(), err) } // the mapping extends from zero to the end of the file mapping // https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-mapviewoffile addr, err := windows.MapViewOfFile(h, syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, 0) if err != nil { - return Data{}, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) + return nil, fmt.Errorf("MapViewOfFile %s: %w", f.Name(), err) } - // need to remember addr and h for unmapping - return Data{f, unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), h}, nil + // Note: previously, we called windows.VirtualQuery here to get the exact + // size of the memory mapped region, but VirtualQuery reported sizes smaller + // than the actual file size (hypothesis: VirtualQuery only reports pages in + // a certain state, and newly written pages may not be counted). + return &Data{f, unsafe.Slice((*byte)(unsafe.Pointer(addr)), size), h}, nil } -func munmapFile(d Data) error { +func munmapFile(d *Data) error { err := windows.UnmapViewOfFile(uintptr(unsafe.Pointer(&d.Data[0]))) x, ok := d.Windows.(windows.Handle) if ok { diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/types.go b/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/types.go index bcd172d97f..7c788b3415 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/types.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/types.go @@ -31,9 +31,9 @@ type CounterConfig struct { Depth int `json:",omitempty"` // for stack counters } -// A Report is what's uploaded (or saved locally) +// A Report is the weekly aggregate of counters. type Report struct { - Week string // first day this report covers (YYYY-MM-DD) + Week string // End day this report covers (YYYY-MM-DD) LastWeek string // Week field from latest previous report uploaded X float64 // A random probability used to determine which counters are uploaded Programs []*ProgramReport diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/upload/findwork.go b/src/cmd/vendor/golang.org/x/telemetry/internal/upload/findwork.go index f1490be3a5..2b165be3f9 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/upload/findwork.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/upload/findwork.go @@ -32,7 +32,7 @@ func (u *uploader) findWork() work { } mode, asof := u.dir.Mode() - u.logger.Printf("Finding work: mode %s, asof %s", mode, asof) + u.logger.Printf("Finding work: mode %s asof %s", mode, asof) // count files end in .v1.count // reports end in .json. If they are not to be uploaded they diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/upload/reports.go b/src/cmd/vendor/golang.org/x/telemetry/internal/upload/reports.go index d1091f40ad..31bda70676 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/upload/reports.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/upload/reports.go @@ -115,8 +115,11 @@ func (u *uploader) deleteFiles(files []string) { } } -// createReport for all the count files for the same date. -// returns the absolute path name of the file containing the report +// createReport creates local and upload report files by +// combining all the count files for the expiryDate, and +// returns the upload report file's path. +// It may delete the count files once local and upload report +// files are successfully created. func (u *uploader) createReport(start time.Time, expiryDate string, countFiles []string, lastWeek string) (string, error) { uploadOK := true mode, asof := u.dir.Mode() diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/upload/upload.go b/src/cmd/vendor/golang.org/x/telemetry/internal/upload/upload.go index 2a3bf70f9d..aa0f4f0c87 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/upload/upload.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/upload/upload.go @@ -65,12 +65,6 @@ func (u *uploader) uploadReportContents(fname string, buf []byte) bool { fdate = fdate[len(fdate)-len("2006-01-02"):] newname := filepath.Join(u.dir.UploadDir(), fdate+".json") - if _, err := os.Stat(newname); err == nil { - // Another process uploaded but failed to clean up (or hasn't yet cleaned - // up). Ensure that cleanup occurs. - _ = os.Remove(fname) - return false - } // Lock the upload, to prevent duplicate uploads. { @@ -84,6 +78,14 @@ func (u *uploader) uploadReportContents(fname string, buf []byte) bool { defer os.Remove(lockname) } + if _, err := os.Stat(newname); err == nil { + // Another process uploaded but failed to clean up (or hasn't yet cleaned + // up). Ensure that cleanup occurs. + u.logger.Printf("After acquire: report already uploaded") + _ = os.Remove(fname) + return false + } + endpoint := u.uploadServerURL + "/" + fdate b := bytes.NewReader(buf) resp, err := http.Post(endpoint, "application/json", b) diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index f4eefe4a1d..8a3cc87dcb 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -25,7 +25,7 @@ golang.org/x/arch/x86/x86asm # golang.org/x/build v0.0.0-20240603162849-5dfbda438323 ## explicit; go 1.21 golang.org/x/build/relnote -# golang.org/x/mod v0.18.0 +# golang.org/x/mod v0.19.0 ## explicit; go 1.18 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile @@ -40,12 +40,12 @@ golang.org/x/mod/zip ## explicit; go 1.18 golang.org/x/sync/errgroup golang.org/x/sync/semaphore -# golang.org/x/sys v0.21.0 +# golang.org/x/sys v0.22.0 ## explicit; go 1.18 golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 +# golang.org/x/telemetry v0.0.0-20240712210958-268b4a8ec2d7 ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter diff --git a/src/go.mod b/src/go.mod index b38dee7e6d..789f5aaa1d 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect ) diff --git a/src/go.sum b/src/go.sum index c5eab7d4b2..a75ea98c73 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.23.1-0.20240603234054-0b431c7de36a h1:37MIv+iGfwMYzWJECGy golang.org/x/crypto v0.23.1-0.20240603234054-0b431c7de36a/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/net v0.25.1-0.20240603202750-6249541f2a6c h1:CR/7/SLUhIJw6g675eeoDiwggElO2MV9rGkNYjqi8GM= golang.org/x/net v0.25.1-0.20240603202750-6249541f2a6c/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index 2868749b89..b8a0b84a28 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -18,7 +18,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.21.0 +# golang.org/x/sys v0.22.0 ## explicit; go 1.18 golang.org/x/sys/cpu # golang.org/x/text v0.16.0 From 5d36bc18d56fa5d7ad10b675dd82892ed3100332 Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Fri, 12 Jul 2024 20:42:50 +0100 Subject: [PATCH 71/72] net/http: document io.Seeker requirement for fs.FS arguments Using the same wording as http.FS, even though it's not strictly required if a content type can be determined by file extension. Fixes #66877 Updates #44553 Change-Id: I7b70c10909bdd289a57d1998a565262b8aaf2dd2 Reviewed-on: https://go-review.googlesource.com/c/go/+/597977 Reviewed-by: Damien Neil Auto-Submit: Ian Lance Taylor Commit-Queue: Ian Lance Taylor Reviewed-by: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/net/http/filetransport.go | 2 +- src/net/http/fs.go | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/net/http/filetransport.go b/src/net/http/filetransport.go index 7384b22fbe..b08bae6348 100644 --- a/src/net/http/filetransport.go +++ b/src/net/http/filetransport.go @@ -35,7 +35,7 @@ func NewFileTransport(fs FileSystem) RoundTripper { // NewFileTransportFS returns a new [RoundTripper], serving the provided // file system fsys. The returned RoundTripper ignores the URL host in its // incoming requests, as well as most other properties of the -// request. +// request. The files provided by fsys must implement [io.Seeker]. // // The typical use case for NewFileTransportFS is to register the "file" // protocol with a [Transport], as in: diff --git a/src/net/http/fs.go b/src/net/http/fs.go index 70653550f0..3a716fbd2c 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -819,6 +819,7 @@ func ServeFile(w ResponseWriter, r *Request, name string) { // ServeFileFS replies to the request with the contents // of the named file or directory from the file system fsys. +// The files provided by fsys must implement [io.Seeker]. // // If the provided name is constructed from user input, it should be // sanitized before calling [ServeFileFS]. @@ -965,6 +966,7 @@ func FileServer(root FileSystem) Handler { // FileServerFS returns a handler that serves HTTP requests // with the contents of the file system fsys. +// The files provided by fsys must implement [io.Seeker]. // // As a special case, the returned file server redirects any request // ending in "/index.html" to the same path, without the final From 8f1ec59bdb2d095b9caf31f6f3fd3e167b14ef0a Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Mon, 15 Jul 2024 23:20:52 +0700 Subject: [PATCH 72/72] strings: re-introduce noescape wrapper CL 573955 added internal/abi:NoEscape function, and use it in strings builder copyCheck code. However, internal/abi is a runtime package, which can not be built with -d=checkptr flag yet. This causes incorrect inlining decision, since NoEscape must not be inlined when -d=checkptr is used. Fixing this by re-introducing noescape wrapper. Fixes #68415 Change-Id: I776cab4c9e9e4b3e58162dcce6ec025cb366bdee Reviewed-on: https://go-review.googlesource.com/c/go/+/598295 Reviewed-by: Michael Knyszek Reviewed-by: Jorropo LUCI-TryBot-Result: Go LUCI Reviewed-by: Keith Randall Auto-Submit: Cuong Manh Le --- src/strings/builder.go | 14 +++++++++++++- test/fixedbugs/issue68415.go | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue68415.go diff --git a/src/strings/builder.go b/src/strings/builder.go index e6df08c6f4..3b37888cbf 100644 --- a/src/strings/builder.go +++ b/src/strings/builder.go @@ -23,6 +23,18 @@ type Builder struct { buf []byte } +// This is just a wrapper around abi.NoEscape. +// +// This wrapper is necessary because internal/abi is a runtime package, +// so it can not be built with -d=checkptr, causing incorrect inlining +// decision when building with checkptr enabled, see issue #68415. +// +//go:nosplit +//go:nocheckptr +func noescape(p unsafe.Pointer) unsafe.Pointer { + return abi.NoEscape(p) +} + func (b *Builder) copyCheck() { if b.addr == nil { // This hack works around a failing of Go's escape analysis @@ -30,7 +42,7 @@ func (b *Builder) copyCheck() { // See issue 23382. // TODO: once issue 7921 is fixed, this should be reverted to // just "b.addr = b". - b.addr = (*Builder)(abi.NoEscape(unsafe.Pointer(b))) + b.addr = (*Builder)(noescape(unsafe.Pointer(b))) } else if b.addr != b { panic("strings: illegal use of non-zero Builder copied by value") } diff --git a/test/fixedbugs/issue68415.go b/test/fixedbugs/issue68415.go new file mode 100644 index 0000000000..cf278ac603 --- /dev/null +++ b/test/fixedbugs/issue68415.go @@ -0,0 +1,15 @@ +// run -gcflags=all=-d=checkptr + +// Copyright 2024 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 main + +import "regexp" + +var dataFileRegexp = regexp.MustCompile(`^data\.\d+\.bin$`) + +func main() { + _ = dataFileRegexp +}