diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-04-12 14:15:16 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-04-12 15:23:16 -0700 |
commit | eb49f7de9341cb464327234c3a673ce3ef642e01 (patch) | |
tree | 44682a0f81f3aeef685487c61e375abe6a0904d5 /libgo/go | |
parent | 84081e2c6bd43a6790f751755865cf4227adac7c (diff) | |
download | gcc-eb49f7de9341cb464327234c3a673ce3ef642e01.zip gcc-eb49f7de9341cb464327234c3a673ce3ef642e01.tar.gz gcc-eb49f7de9341cb464327234c3a673ce3ef642e01.tar.bz2 |
libgo: update to Go1.16.3 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/309490
Diffstat (limited to 'libgo/go')
-rw-r--r-- | libgo/go/cmd/go.mod | 2 | ||||
-rw-r--r-- | libgo/go/cmd/go/alldocs.go | 20 | ||||
-rw-r--r-- | libgo/go/cmd/go/internal/modfetch/cache.go | 17 | ||||
-rw-r--r-- | libgo/go/cmd/go/internal/modfetch/fetch.go | 77 | ||||
-rw-r--r-- | libgo/go/cmd/go/internal/work/build.go | 20 | ||||
-rw-r--r-- | libgo/go/cmd/go/testdata/script/mod_verify.txt | 7 | ||||
-rw-r--r-- | libgo/go/cmd/vendor/modules.txt | 2 | ||||
-rw-r--r-- | libgo/go/golang.org/x/mod/module/module.go | 38 | ||||
-rw-r--r-- | libgo/go/runtime/symtab_test.go | 85 | ||||
-rw-r--r-- | libgo/go/runtime/time.go | 5 | ||||
-rw-r--r-- | libgo/go/testing/helper_test.go | 32 | ||||
-rw-r--r-- | libgo/go/testing/testing.go | 15 | ||||
-rw-r--r-- | libgo/go/time/sleep_test.go | 16 |
13 files changed, 271 insertions, 65 deletions
diff --git a/libgo/go/cmd/go.mod b/libgo/go/cmd/go.mod index 35582f3..70b1b06 100644 --- a/libgo/go/cmd/go.mod +++ b/libgo/go/cmd/go.mod @@ -6,7 +6,7 @@ require ( github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2 golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 - golang.org/x/mod v0.4.2-0.20210302225053-d515b24adc21 + golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea golang.org/x/sys v0.0.0-20201204225414-ed752295db88 // indirect golang.org/x/tools v0.0.0-20210107193943-4ed967dd8eff ) diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go index e7c63f0..84f89c9 100644 --- a/libgo/go/cmd/go/alldocs.go +++ b/libgo/go/cmd/go/alldocs.go @@ -692,18 +692,22 @@ // arguments must satisfy the following constraints: // // - Arguments must be package paths or package patterns (with "..." wildcards). -// They must not be standard packages (like fmt), meta-patterns (std, cmd, -// all), or relative or absolute file paths. +// They must not be standard packages (like fmt), meta-patterns (std, cmd, +// all), or relative or absolute file paths. +// // - All arguments must have the same version suffix. Different queries are not -// allowed, even if they refer to the same version. +// allowed, even if they refer to the same version. +// // - All arguments must refer to packages in the same module at the same version. +// // - No module is considered the "main" module. If the module containing -// packages named on the command line has a go.mod file, it must not contain -// directives (replace and exclude) that would cause it to be interpreted -// differently than if it were the main module. The module must not require -// a higher version of itself. +// packages named on the command line has a go.mod file, it must not contain +// directives (replace and exclude) that would cause it to be interpreted +// differently than if it were the main module. The module must not require +// a higher version of itself. +// // - Package path arguments must refer to main packages. Pattern arguments -// will only match main packages. +// will only match main packages. // // If the arguments don't have version suffixes, "go install" may run in // module-aware mode or GOPATH mode, depending on the GO111MODULE environment diff --git a/libgo/go/cmd/go/internal/modfetch/cache.go b/libgo/go/cmd/go/internal/modfetch/cache.go index 3a2ff63..07e046c8 100644 --- a/libgo/go/cmd/go/internal/modfetch/cache.go +++ b/libgo/go/cmd/go/internal/modfetch/cache.go @@ -84,6 +84,7 @@ func DownloadDir(m module.Version) (string, error) { return "", err } + // Check whether the directory itself exists. dir := filepath.Join(cfg.GOMODCACHE, enc+"@"+encVer) if fi, err := os.Stat(dir); os.IsNotExist(err) { return dir, err @@ -92,6 +93,9 @@ func DownloadDir(m module.Version) (string, error) { } else if !fi.IsDir() { return dir, &DownloadDirPartialError{dir, errors.New("not a directory")} } + + // Check if a .partial file exists. This is created at the beginning of + // a download and removed after the zip is extracted. partialPath, err := CachePath(m, "partial") if err != nil { return dir, err @@ -101,6 +105,19 @@ func DownloadDir(m module.Version) (string, error) { } else if !os.IsNotExist(err) { return dir, err } + + // Check if a .ziphash file exists. It should be created before the + // zip is extracted, but if it was deleted (by another program?), we need + // to re-calculate it. + ziphashPath, err := CachePath(m, "ziphash") + if err != nil { + return dir, err + } + if _, err := os.Stat(ziphashPath); os.IsNotExist(err) { + return dir, &DownloadDirPartialError{dir, errors.New("ziphash file is missing")} + } else if err != nil { + return dir, err + } return dir, nil } diff --git a/libgo/go/cmd/go/internal/modfetch/fetch.go b/libgo/go/cmd/go/internal/modfetch/fetch.go index c55c3cf..eb7d30e 100644 --- a/libgo/go/cmd/go/internal/modfetch/fetch.go +++ b/libgo/go/cmd/go/internal/modfetch/fetch.go @@ -170,13 +170,16 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e if err != nil { return cached{"", err} } + ziphashfile := zipfile + "hash" - // Skip locking if the zipfile already exists. + // Return without locking if the zip and ziphash files exist. if _, err := os.Stat(zipfile); err == nil { - return cached{zipfile, nil} + if _, err := os.Stat(ziphashfile); err == nil { + return cached{zipfile, nil} + } } - // The zip file does not exist. Acquire the lock and create it. + // The zip or ziphash file does not exist. Acquire the lock and create them. if cfg.CmdName != "mod download" { fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version) } @@ -186,14 +189,6 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e } defer unlock() - // Double-check that the zipfile was not created while we were waiting for - // the lock. - if _, err := os.Stat(zipfile); err == nil { - return cached{zipfile, nil} - } - if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil { - return cached{"", err} - } if err := downloadZip(ctx, mod, zipfile); err != nil { return cached{"", err} } @@ -206,6 +201,25 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e ctx, span := trace.StartSpan(ctx, "modfetch.downloadZip "+zipfile) defer span.Done() + // Double-check that the zipfile was not created while we were waiting for + // the lock in DownloadZip. + ziphashfile := zipfile + "hash" + var zipExists, ziphashExists bool + if _, err := os.Stat(zipfile); err == nil { + zipExists = true + } + if _, err := os.Stat(ziphashfile); err == nil { + ziphashExists = true + } + if zipExists && ziphashExists { + return nil + } + + // Create parent directories. + if err := os.MkdirAll(filepath.Dir(zipfile), 0777); err != nil { + return err + } + // Clean up any remaining tempfiles from previous runs. // This is only safe to do because the lock file ensures that their // writers are no longer active. @@ -217,6 +231,12 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e } } + // If the zip file exists, the ziphash file must have been deleted + // or lost after a file system crash. Re-hash the zip without downloading. + if zipExists { + return hashZip(mod, zipfile, ziphashfile) + } + // From here to the os.Rename call below is functionally almost equivalent to // renameio.WriteToFile, with one key difference: we want to validate the // contents of the file (by hashing it) before we commit it. Because the file @@ -289,15 +309,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e } // Hash the zip file and check the sum before renaming to the final location. - hash, err := dirhash.HashZip(f.Name(), dirhash.DefaultHash) - if err != nil { - return err - } - if err := checkModSum(mod, hash); err != nil { - return err - } - - if err := renameio.WriteFile(zipfile+"hash", []byte(hash), 0666); err != nil { + if err := hashZip(mod, f.Name(), ziphashfile); err != nil { return err } if err := os.Rename(f.Name(), zipfile); err != nil { @@ -309,6 +321,22 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e return nil } +// hashZip reads the zip file opened in f, then writes the hash to ziphashfile, +// overwriting that file if it exists. +// +// If the hash does not match go.sum (or the sumdb if enabled), hashZip returns +// an error and does not write ziphashfile. +func hashZip(mod module.Version, zipfile, ziphashfile string) error { + hash, err := dirhash.HashZip(zipfile, dirhash.DefaultHash) + if err != nil { + return err + } + if err := checkModSum(mod, hash); err != nil { + return err + } + return renameio.WriteFile(ziphashfile, []byte(hash), 0666) +} + // makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir // and its transitive contents. func makeDirsReadOnly(dir string) { @@ -452,11 +480,6 @@ func HaveSum(mod module.Version) bool { // checkMod checks the given module's checksum. func checkMod(mod module.Version) { - if cfg.GOMODCACHE == "" { - // Do not use current directory. - return - } - // Do the file I/O before acquiring the go.sum lock. ziphash, err := CachePath(mod, "ziphash") if err != nil { @@ -464,10 +487,6 @@ func checkMod(mod module.Version) { } data, err := renameio.ReadFile(ziphash) if err != nil { - if errors.Is(err, fs.ErrNotExist) { - // This can happen if someone does rm -rf GOPATH/src/cache/download. So it goes. - return - } base.Fatalf("verifying %v", module.VersionError(mod, err)) } h := strings.TrimSpace(string(data)) diff --git a/libgo/go/cmd/go/internal/work/build.go b/libgo/go/cmd/go/internal/work/build.go index 780d639..f024b07 100644 --- a/libgo/go/cmd/go/internal/work/build.go +++ b/libgo/go/cmd/go/internal/work/build.go @@ -482,18 +482,22 @@ To eliminate ambiguity about which module versions are used in the build, the arguments must satisfy the following constraints: - Arguments must be package paths or package patterns (with "..." wildcards). - They must not be standard packages (like fmt), meta-patterns (std, cmd, - all), or relative or absolute file paths. +They must not be standard packages (like fmt), meta-patterns (std, cmd, +all), or relative or absolute file paths. + - All arguments must have the same version suffix. Different queries are not - allowed, even if they refer to the same version. +allowed, even if they refer to the same version. + - All arguments must refer to packages in the same module at the same version. + - No module is considered the "main" module. If the module containing - packages named on the command line has a go.mod file, it must not contain - directives (replace and exclude) that would cause it to be interpreted - differently than if it were the main module. The module must not require - a higher version of itself. +packages named on the command line has a go.mod file, it must not contain +directives (replace and exclude) that would cause it to be interpreted +differently than if it were the main module. The module must not require +a higher version of itself. + - Package path arguments must refer to main packages. Pattern arguments - will only match main packages. +will only match main packages. If the arguments don't have version suffixes, "go install" may run in module-aware mode or GOPATH mode, depending on the GO111MODULE environment diff --git a/libgo/go/cmd/go/testdata/script/mod_verify.txt b/libgo/go/cmd/go/testdata/script/mod_verify.txt index 43812d0..b5106659 100644 --- a/libgo/go/cmd/go/testdata/script/mod_verify.txt +++ b/libgo/go/cmd/go/testdata/script/mod_verify.txt @@ -48,10 +48,13 @@ go mod tidy grep '^rsc.io/quote v1.1.0/go.mod ' go.sum grep '^rsc.io/quote v1.1.0 ' go.sum -# sync should ignore missing ziphash; verify should not +# verify should fail on a missing ziphash. tidy should restore it. rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash -go mod tidy ! go mod verify +stderr '^rsc.io/quote v1.1.0: missing ziphash: open '$GOPATH'[/\\]pkg[/\\]mod[/\\]cache[/\\]download[/\\]rsc.io[/\\]quote[/\\]@v[/\\]v1.1.0.ziphash' +go mod tidy +exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.1.0.ziphash +go mod verify # Packages below module root should not be mentioned in go.sum. rm go.sum diff --git a/libgo/go/cmd/vendor/modules.txt b/libgo/go/cmd/vendor/modules.txt index 1084276..ae2c0a0 100644 --- a/libgo/go/cmd/vendor/modules.txt +++ b/libgo/go/cmd/vendor/modules.txt @@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm golang.org/x/crypto/ed25519 golang.org/x/crypto/ed25519/internal/edwards25519 golang.org/x/crypto/ssh/terminal -# golang.org/x/mod v0.4.2-0.20210302225053-d515b24adc21 +# golang.org/x/mod v0.4.2-0.20210325185522-dbbbf8a3c6ea ## explicit golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile diff --git a/libgo/go/golang.org/x/mod/module/module.go b/libgo/go/golang.org/x/mod/module/module.go index 272baee..0e03014 100644 --- a/libgo/go/golang.org/x/mod/module/module.go +++ b/libgo/go/golang.org/x/mod/module/module.go @@ -224,12 +224,16 @@ func firstPathOK(r rune) bool { 'a' <= r && r <= 'z' } -// pathOK reports whether r can appear in an import path element. +// modPathOK reports whether r can appear in a module path element. // Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~. -// This matches what "go get" has historically recognized in import paths. +// +// This matches what "go get" has historically recognized in import paths, +// and avoids confusing sequences like '%20' or '+' that would change meaning +// if used in a URL. +// // TODO(rsc): We would like to allow Unicode letters, but that requires additional // care in the safe encoding (see "escaped paths" above). -func pathOK(r rune) bool { +func modPathOK(r rune) bool { if r < utf8.RuneSelf { return r == '-' || r == '.' || r == '_' || r == '~' || '0' <= r && r <= '9' || @@ -239,6 +243,17 @@ func pathOK(r rune) bool { return false } +// modPathOK reports whether r can appear in a package import path element. +// +// Import paths are intermediate between module paths and file paths: we allow +// disallow characters that would be confusing or ambiguous as arguments to +// 'go get' (such as '@' and ' ' ), but allow certain characters that are +// otherwise-unambiguous on the command line and historically used for some +// binary names (such as '++' as a suffix for compiler binaries and wrappers). +func importPathOK(r rune) bool { + return modPathOK(r) || r == '+' +} + // fileNameOK reports whether r can appear in a file name. // For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters. // If we expand the set of allowed characters here, we have to @@ -394,12 +409,19 @@ func checkElem(elem string, kind pathKind) error { if elem[len(elem)-1] == '.' { return fmt.Errorf("trailing dot in path element") } - charOK := pathOK - if kind == filePath { - charOK = fileNameOK - } for _, r := range elem { - if !charOK(r) { + ok := false + switch kind { + case modulePath: + ok = modPathOK(r) + case importPath: + ok = importPathOK(r) + case filePath: + ok = fileNameOK(r) + default: + panic(fmt.Sprintf("internal error: invalid kind %v", kind)) + } + if !ok { return fmt.Errorf("invalid char %q", r) } } diff --git a/libgo/go/runtime/symtab_test.go b/libgo/go/runtime/symtab_test.go index 807b50d..ddf64f6 100644 --- a/libgo/go/runtime/symtab_test.go +++ b/libgo/go/runtime/symtab_test.go @@ -8,6 +8,7 @@ import ( "runtime" "strings" "testing" + "unsafe" ) var _ = runtime.Caller @@ -171,3 +172,87 @@ func TestNilName(t *testing.T) { t.Errorf("Name() = %q, want %q", got, "") } } + +var dummy int + +func inlined() { + // Side effect to prevent elimination of this entire function. + dummy = 42 +} + +// A function with an InlTree. Returns a PC within the function body. +// +// No inline to ensure this complete function appears in output. +// +//go:noinline +func tracebackFunc(t *testing.T) uintptr { + // This body must be more complex than a single call to inlined to get + // an inline tree. + inlined() + inlined() + + // Acquire a PC in this function. + pc, _, _, ok := runtime.Caller(0) + if !ok { + t.Fatalf("Caller(0) got ok false, want true") + } + + return pc +} + +// Test that CallersFrames handles PCs in the alignment region between +// functions (int 3 on amd64) without crashing. +// +// Go will never generate a stack trace containing such an address, as it is +// not a valid call site. However, the cgo traceback function passed to +// runtime.SetCgoTraceback may not be completely accurate and may incorrect +// provide PCs in Go code or the alignement region between functions. +// +// Go obviously doesn't easily expose the problematic PCs to running programs, +// so this test is a bit fragile. Some details: +// +// * tracebackFunc is our target function. We want to get a PC in the +// alignment region following this function. This function also has other +// functions inlined into it to ensure it has an InlTree (this was the source +// of the bug in issue 44971). +// +// * We acquire a PC in tracebackFunc, walking forwards until FuncForPC says +// we're in a new function. The last PC of the function according to FuncForPC +// should be in the alignment region (assuming the function isn't already +// perfectly aligned). +// +// This is a regression test for issue 44971. +func TestFunctionAlignmentTraceback(t *testing.T) { + pc := tracebackFunc(t) + + // Double-check we got the right PC. + f := runtime.FuncForPC(pc) + if !strings.HasSuffix(f.Name(), "tracebackFunc") { + t.Fatalf("Caller(0) = %+v, want tracebackFunc", f) + } + + // Iterate forward until we find a different function. Back up one + // instruction is (hopefully) an alignment instruction. + for runtime.FuncForPC(pc) == f { + pc++ + } + pc-- + + // Is this an alignment region filler instruction? We only check this + // on amd64 for simplicity. If this function has no filler, then we may + // get a false negative, but will never get a false positive. + if runtime.GOARCH == "amd64" && runtime.Compiler == "gc" { + code := *(*uint8)(unsafe.Pointer(pc)) + if code != 0xcc { // INT $3 + t.Errorf("PC %v code got %#x want 0xcc", pc, code) + } + } + + // Finally ensure that Frames.Next doesn't crash when processing this + // PC. + frames := runtime.CallersFrames([]uintptr{pc}) + frame, _ := frames.Next() + if *frame.Func != *f { + t.Errorf("frames.Next() got %+v want %+v", frame.Func, f) + } +} diff --git a/libgo/go/runtime/time.go b/libgo/go/runtime/time.go index a69db99..327726c 100644 --- a/libgo/go/runtime/time.go +++ b/libgo/go/runtime/time.go @@ -262,6 +262,9 @@ func addtimer(t *timer) { when := t.when + // Disable preemption while using pp to avoid changing another P's heap. + mp := acquirem() + pp := getg().m.p.ptr() lock(&pp.timersLock) cleantimers(pp) @@ -269,6 +272,8 @@ func addtimer(t *timer) { unlock(&pp.timersLock) wakeNetPoller(when) + + releasem(mp) } // doaddtimer adds t to the current P's heap. diff --git a/libgo/go/testing/helper_test.go b/libgo/go/testing/helper_test.go index 8858196..b27fd62 100644 --- a/libgo/go/testing/helper_test.go +++ b/libgo/go/testing/helper_test.go @@ -71,6 +71,38 @@ func TestTBHelperParallel(t *T) { } } +func TestTBHelperLineNumer(t *T) { + var buf bytes.Buffer + ctx := newTestContext(1, newMatcher(regexp.MatchString, "", "")) + t1 := &T{ + common: common{ + signal: make(chan bool), + w: &buf, + }, + context: ctx, + } + t1.Run("Test", func(t *T) { + helperA := func(t *T) { + t.Helper() + t.Run("subtest", func(t *T) { + t.Helper() + t.Fatal("fatal error message") + }) + } + helperA(t) + }) + + want := "helper_test.go:92: fatal error message" + got := "" + lines := strings.Split(strings.TrimSpace(buf.String()), "\n") + if len(lines) > 0 { + got = strings.TrimSpace(lines[len(lines)-1]) + } + if got != want { + t.Errorf("got output:\n\n%v\nwant:\n\n%v", got, want) + } +} + type noopWriter int func (nw *noopWriter) Write(b []byte) (int, error) { return len(b), nil } diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index 795ee32..143d81c 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -509,6 +509,13 @@ func (c *common) frameSkip(skip int) runtime.Frame { } return prevFrame } + // If more helper PCs have been added since we last did the conversion + if c.helperNames == nil { + c.helperNames = make(map[string]struct{}) + for pc := range c.helperPCs { + c.helperNames[pcToName(pc)] = struct{}{} + } + } if _, ok := c.helperNames[frame.Function]; !ok { // Found a frame that wasn't inside a helper function. return frame @@ -521,14 +528,6 @@ func (c *common) frameSkip(skip int) runtime.Frame { // and inserts the final newline if needed and indentation spaces for formatting. // This function must be called with c.mu held. func (c *common) decorate(s string, skip int) string { - // If more helper PCs have been added since we last did the conversion - if c.helperNames == nil { - c.helperNames = make(map[string]struct{}) - for pc := range c.helperPCs { - c.helperNames[pcToName(pc)] = struct{}{} - } - } - frame := c.frameSkip(skip) file := frame.File line := frame.Line diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go index 86b634c..fb66e70 100644 --- a/libgo/go/time/sleep_test.go +++ b/libgo/go/time/sleep_test.go @@ -512,6 +512,22 @@ func TestZeroTimerStopPanics(t *testing.T) { tr.Stop() } +// Test that zero duration timers aren't missed by the scheduler. Regression test for issue 44868. +func TestZeroTimer(t *testing.T) { + if testing.Short() { + t.Skip("-short") + } + + for i := 0; i < 1000000; i++ { + s := Now() + ti := NewTimer(0) + <-ti.C + if diff := Since(s); diff > 2*Second { + t.Errorf("Expected time to get value from Timer channel in less than 2 sec, took %v", diff) + } + } +} + // Benchmark timer latency when the thread that creates the timer is busy with // other work and the timers must be serviced by other threads. // https://golang.org/issue/38860 |