libgo: update to Go1.16.3 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/309490
This commit is contained in:
parent
84081e2c6b
commit
eb49f7de93
21 changed files with 355 additions and 68 deletions
|
@ -1,4 +1,4 @@
|
|||
4bdff733a0c2a9ddc3eff104b1be03df058a79c4
|
||||
9782e85bef1c16c72a4980856d921cea104b129c
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
3979fb9af9ccfc0b7ccb613dcf256b18c2c295f0
|
||||
9baddd3f21230c55f0ad2a10f5f20579dcf0a0bb
|
||||
|
||||
The first line of this file holds the git revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
|
|
@ -1 +1 @@
|
|||
go1.16.2
|
||||
go1.16.3
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
2
libgo/go/cmd/vendor/modules.txt
vendored
2
libgo/go/cmd/vendor/modules.txt
vendored
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -209,3 +209,10 @@ func TestMethod2(t *testing.T) {
|
|||
goCmd(t, "build", "-o", "method2.exe", "./method2/main.go")
|
||||
run(t, "./method2.exe")
|
||||
}
|
||||
|
||||
func TestIssue44956(t *testing.T) {
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go")
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go")
|
||||
goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go")
|
||||
run(t, "./issue44956.exe")
|
||||
}
|
||||
|
|
7
libgo/misc/cgo/testplugin/testdata/issue44956/base/base.go
vendored
Normal file
7
libgo/misc/cgo/testplugin/testdata/issue44956/base/base.go
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2021 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 base
|
||||
|
||||
var X = &map[int]int{123: 456}
|
47
libgo/misc/cgo/testplugin/testdata/issue44956/main.go
vendored
Normal file
47
libgo/misc/cgo/testplugin/testdata/issue44956/main.go
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
// Copyright 2021 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.
|
||||
|
||||
// Issue 44956: writable static temp is not exported correctly.
|
||||
// In the test below, package base is
|
||||
//
|
||||
// X = &map{...}
|
||||
//
|
||||
// which compiles to
|
||||
//
|
||||
// X = &stmp // static
|
||||
// stmp = makemap(...) // in init function
|
||||
//
|
||||
// plugin1 and plugin2 both import base. plugin1 doesn't use
|
||||
// base.X, so that symbol is deadcoded in plugin1.
|
||||
//
|
||||
// plugin1 is loaded first. base.init runs at that point, which
|
||||
// initialize base.stmp.
|
||||
//
|
||||
// plugin2 is then loaded. base.init already ran, so it doesn't run
|
||||
// again. When base.stmp is not exported, plugin2's base.X points to
|
||||
// its own private base.stmp, which is not initialized, fail.
|
||||
|
||||
package main
|
||||
|
||||
import "plugin"
|
||||
|
||||
func main() {
|
||||
_, err := plugin.Open("issue44956p1.so")
|
||||
if err != nil {
|
||||
panic("FAIL")
|
||||
}
|
||||
|
||||
p2, err := plugin.Open("issue44956p2.so")
|
||||
if err != nil {
|
||||
panic("FAIL")
|
||||
}
|
||||
f, err := p2.Lookup("F")
|
||||
if err != nil {
|
||||
panic("FAIL")
|
||||
}
|
||||
x := f.(func() *map[int]int)()
|
||||
if x == nil || (*x)[123] != 456 {
|
||||
panic("FAIL")
|
||||
}
|
||||
}
|
9
libgo/misc/cgo/testplugin/testdata/issue44956/plugin1.go
vendored
Normal file
9
libgo/misc/cgo/testplugin/testdata/issue44956/plugin1.go
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2021 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 _ "testplugin/issue44956/base"
|
||||
|
||||
func main() {}
|
11
libgo/misc/cgo/testplugin/testdata/issue44956/plugin2.go
vendored
Normal file
11
libgo/misc/cgo/testplugin/testdata/issue44956/plugin2.go
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2021 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 "testplugin/issue44956/base"
|
||||
|
||||
func F() *map[int]int { return base.X }
|
||||
|
||||
func main() {}
|
Loading…
Add table
Reference in a new issue