libgo: update to final Go 1.17 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/343729
This commit is contained in:
parent
a827909537
commit
74df79ec3e
13 changed files with 218 additions and 68 deletions
|
@ -1,4 +1,4 @@
|
|||
77bc32767b61feb6499ca7921e96b356603517dc
|
||||
b3fad6957a04520013197ea7cab11bec3298d552
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
72ab3ff68b1ec894fe5599ec82b8849f3baa9d94
|
||||
ec5170397c724a8ae440b2bc529f857c86f0e6b1
|
||||
|
||||
The first line of this file holds the git revision number of the
|
||||
last merge done from the master library sources.
|
||||
|
|
|
@ -1 +1 @@
|
|||
go1.17rc2
|
||||
go1.17
|
||||
|
|
|
@ -191,6 +191,19 @@ func (rs *Requirements) rootSelected(path string) (version string, ok bool) {
|
|||
return "", false
|
||||
}
|
||||
|
||||
// hasRedundantRoot returns true if the root list contains multiple requirements
|
||||
// of the same module or a requirement on any version of the main module.
|
||||
// Redundant requirements should be pruned, but they may influence version
|
||||
// selection.
|
||||
func (rs *Requirements) hasRedundantRoot() bool {
|
||||
for i, m := range rs.rootModules {
|
||||
if m.Path == Target.Path || (i > 0 && m.Path == rs.rootModules[i-1].Path) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Graph returns the graph of module requirements loaded from the current
|
||||
// root modules (as reported by RootModules).
|
||||
//
|
||||
|
@ -882,6 +895,12 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen
|
|||
// and (trivially) version.
|
||||
|
||||
if !rootsUpgraded {
|
||||
if cfg.BuildMod != "mod" {
|
||||
// The only changes to the root set (if any) were to remove duplicates.
|
||||
// The requirements are consistent (if perhaps redundant), so keep the
|
||||
// original rs to preserve its ModuleGraph.
|
||||
return rs, nil
|
||||
}
|
||||
// The root set has converged: every root going into this iteration was
|
||||
// already at its selected version, although we have have removed other
|
||||
// (redundant) roots for the same path.
|
||||
|
|
|
@ -449,13 +449,22 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
|
|||
}
|
||||
|
||||
setDefaultBuildMod() // possibly enable automatic vendoring
|
||||
rs = requirementsFromModFile(ctx)
|
||||
|
||||
rs = requirementsFromModFile()
|
||||
if cfg.BuildMod == "vendor" {
|
||||
readVendorList()
|
||||
checkVendorConsistency()
|
||||
rs.initVendor(vendorList)
|
||||
}
|
||||
if rs.hasRedundantRoot() {
|
||||
// If any module path appears more than once in the roots, we know that the
|
||||
// go.mod file needs to be updated even though we have not yet loaded any
|
||||
// transitive dependencies.
|
||||
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if index.goVersionV == "" {
|
||||
// TODO(#45551): Do something more principled instead of checking
|
||||
// cfg.CmdName directly here.
|
||||
|
@ -530,7 +539,12 @@ func CreateModFile(ctx context.Context, modPath string) {
|
|||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
|
||||
commitRequirements(ctx, modFileGoVersion(), requirementsFromModFile(ctx))
|
||||
rs := requirementsFromModFile()
|
||||
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
commitRequirements(ctx, modFileGoVersion(), rs)
|
||||
|
||||
// Suggest running 'go mod tidy' unless the project is empty. Even if we
|
||||
// imported all the correct requirements above, we're probably missing
|
||||
|
@ -641,9 +655,8 @@ func initTarget(m module.Version) {
|
|||
|
||||
// requirementsFromModFile returns the set of non-excluded requirements from
|
||||
// the global modFile.
|
||||
func requirementsFromModFile(ctx context.Context) *Requirements {
|
||||
func requirementsFromModFile() *Requirements {
|
||||
roots := make([]module.Version, 0, len(modFile.Require))
|
||||
mPathCount := map[string]int{Target.Path: 1}
|
||||
direct := map[string]bool{}
|
||||
for _, r := range modFile.Require {
|
||||
if index != nil && index.exclude[r.Mod] {
|
||||
|
@ -656,28 +669,12 @@ func requirementsFromModFile(ctx context.Context) *Requirements {
|
|||
}
|
||||
|
||||
roots = append(roots, r.Mod)
|
||||
mPathCount[r.Mod.Path]++
|
||||
if !r.Indirect {
|
||||
direct[r.Mod.Path] = true
|
||||
}
|
||||
}
|
||||
module.Sort(roots)
|
||||
rs := newRequirements(modDepthFromGoVersion(modFileGoVersion()), roots, direct)
|
||||
|
||||
// If any module path appears more than once in the roots, we know that the
|
||||
// go.mod file needs to be updated even though we have not yet loaded any
|
||||
// transitive dependencies.
|
||||
for _, n := range mPathCount {
|
||||
if n > 1 {
|
||||
var err error
|
||||
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return rs
|
||||
}
|
||||
|
||||
|
|
|
@ -2,18 +2,13 @@
|
|||
# 'go mod tidy' should not panic if the main module initially
|
||||
# requires an older version of itself.
|
||||
|
||||
# A module may require an older version of itself without error. This is
|
||||
# inconsistent (the required version is never selected), but we still get
|
||||
# a reproducible build list.
|
||||
go list -m all
|
||||
stdout '^golang.org/issue/46078$'
|
||||
|
||||
# A module that explicitly requires an older version of itself should be
|
||||
# rejected as inconsistent: we enforce that every explicit requirement is the
|
||||
# selected version of its module path, but the selected version of the main
|
||||
# module is always itself — not some explicit version.
|
||||
|
||||
! go list -m all
|
||||
stderr '^go: updates to go\.mod needed; to update it:\n\tgo mod tidy$'
|
||||
|
||||
|
||||
# The suggested 'go mod tidy' command should succeed (not crash).
|
||||
|
||||
# 'go mod tidy' should fix this (and not crash).
|
||||
go mod tidy
|
||||
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ type File interface {
|
|||
type DirEntry interface {
|
||||
// Name returns the name of the file (or subdirectory) described by the entry.
|
||||
// This name is only the final element of the path (the base name), not the entire path.
|
||||
// For example, Name would return "hello.go" not "/home/gopher/hello.go".
|
||||
// For example, Name would return "hello.go" not "home/gopher/hello.go".
|
||||
Name() string
|
||||
|
||||
// IsDir reports whether the entry describes a directory.
|
||||
|
|
|
@ -6445,10 +6445,11 @@ func TestErrorWriteLoopRace(t *testing.T) {
|
|||
// Test that a new request which uses the connection of an active request
|
||||
// cannot cause it to be canceled as well.
|
||||
func TestCancelRequestWhenSharingConnection(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping in short mode")
|
||||
}
|
||||
reqc := make(chan chan struct{}, 2)
|
||||
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, req *Request) {
|
||||
ch := make(chan struct{}, 1)
|
||||
reqc <- ch
|
||||
<-ch
|
||||
w.Header().Add("Content-Length", "0")
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
@ -6460,34 +6461,58 @@ func TestCancelRequestWhenSharingConnection(t *testing.T) {
|
|||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for ctx.Err() == nil {
|
||||
reqctx, reqcancel := context.WithCancel(ctx)
|
||||
go reqcancel()
|
||||
req, _ := NewRequestWithContext(reqctx, "GET", ts.URL, nil)
|
||||
res, err := client.Do(req)
|
||||
if err == nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for ctx.Err() == nil {
|
||||
req, _ := NewRequest("GET", ts.URL, nil)
|
||||
if res, err := client.Do(req); err != nil {
|
||||
t.Errorf("unexpected: %p %v", req, err)
|
||||
break
|
||||
} else {
|
||||
wg.Add(1)
|
||||
putidlec := make(chan chan struct{})
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
ctx := httptrace.WithClientTrace(context.Background(), &httptrace.ClientTrace{
|
||||
PutIdleConn: func(error) {
|
||||
// Signal that the idle conn has been returned to the pool,
|
||||
// and wait for the order to proceed.
|
||||
ch := make(chan struct{})
|
||||
putidlec <- ch
|
||||
<-ch
|
||||
},
|
||||
})
|
||||
req, _ := NewRequestWithContext(ctx, "GET", ts.URL, nil)
|
||||
res, err := client.Do(req)
|
||||
if err == nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("request 1: got err %v, want nil", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for the first request to receive a response and return the
|
||||
// connection to the idle pool.
|
||||
r1c := <-reqc
|
||||
close(r1c)
|
||||
idlec := <-putidlec
|
||||
|
||||
wg.Add(1)
|
||||
cancelctx, cancel := context.WithCancel(context.Background())
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
req, _ := NewRequestWithContext(cancelctx, "GET", ts.URL, nil)
|
||||
res, err := client.Do(req)
|
||||
if err == nil {
|
||||
res.Body.Close()
|
||||
}
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
t.Errorf("request 2: got err %v, want Canceled", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for the second request to arrive at the server, and then cancel
|
||||
// the request context.
|
||||
r2c := <-reqc
|
||||
cancel()
|
||||
|
||||
// Give the cancelation a moment to take effect, and then unblock the first request.
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
close(idlec)
|
||||
|
||||
close(r2c)
|
||||
wg.Wait()
|
||||
}
|
||||
|
|
|
@ -402,6 +402,10 @@ okarg:
|
|||
// Without the KeepAlive call, the finalizer could run at the start of
|
||||
// syscall.Read, closing the file descriptor before syscall.Read makes
|
||||
// the actual system call.
|
||||
//
|
||||
// Note: KeepAlive should only be used to prevent finalizers from
|
||||
// running prematurely. In particular, when used with unsafe.Pointer,
|
||||
// the rules for valid uses of unsafe.Pointer still apply.
|
||||
func KeepAlive(x interface{}) {
|
||||
// Introduce a use of x that the compiler can't eliminate.
|
||||
// This makes sure x is alive on entry. We need x to be alive
|
||||
|
|
|
@ -126,7 +126,7 @@ func (v *Value) Swap(new interface{}) (old interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
// CompareAndSwapPointer executes the compare-and-swap operation for the Value.
|
||||
// CompareAndSwap executes the compare-and-swap operation for the Value.
|
||||
//
|
||||
// All calls to CompareAndSwap for a given Value must use values of the same
|
||||
// concrete type. CompareAndSwap of an inconsistent type panics, as does
|
||||
|
|
|
@ -77,9 +77,9 @@ import "errors"
|
|||
// The formats and 002 are space-padded and zero-padded
|
||||
// three-character day of year; there is no unpadded day of year format.
|
||||
//
|
||||
// A decimal point followed by one or more zeros represents a fractional
|
||||
// second, printed to the given number of decimal places.
|
||||
// Either a comma or decimal point followed by one or more nines represents
|
||||
// A comma or decimal point followed by one or more zeros represents
|
||||
// a fractional second, printed to the given number of decimal places.
|
||||
// A comma or decimal point followed by one or more nines represents
|
||||
// a fractional second, printed to the given number of decimal places, with
|
||||
// trailing zeros removed.
|
||||
// For example "15:04:05,000" or "15:04:05.000" formats or parses with
|
||||
|
|
|
@ -42,6 +42,7 @@ func TestMSAN(t *testing.T) {
|
|||
{src: "msan5.go"},
|
||||
{src: "msan6.go"},
|
||||
{src: "msan7.go"},
|
||||
{src: "msan8.go"},
|
||||
{src: "msan_fail.go", wantErr: true},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
|
109
libgo/misc/cgo/testsanitizers/testdata/msan8.go
vendored
Normal file
109
libgo/misc/cgo/testsanitizers/testdata/msan8.go
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
// 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
|
||||
|
||||
/*
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sanitizer/msan_interface.h>
|
||||
|
||||
// cgoTracebackArg is the type of the argument passed to msanGoTraceback.
|
||||
struct cgoTracebackArg {
|
||||
uintptr_t context;
|
||||
uintptr_t sigContext;
|
||||
uintptr_t* buf;
|
||||
uintptr_t max;
|
||||
};
|
||||
|
||||
// msanGoTraceback is registered as the cgo traceback function.
|
||||
// This will be called when a signal occurs.
|
||||
void msanGoTraceback(void* parg) {
|
||||
struct cgoTracebackArg* arg = (struct cgoTracebackArg*)(parg);
|
||||
arg->buf[0] = 0;
|
||||
}
|
||||
|
||||
// msanGoWait will be called with all registers undefined as far as
|
||||
// msan is concerned. It just waits for a signal.
|
||||
// Because the registers are msan-undefined, the signal handler will
|
||||
// be invoked with all registers msan-undefined.
|
||||
__attribute__((noinline))
|
||||
void msanGoWait(unsigned long a1, unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5, unsigned long a6) {
|
||||
sigset_t mask;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigsuspend(&mask);
|
||||
}
|
||||
|
||||
// msanGoSignalThread is the thread ID of the msanGoLoop thread.
|
||||
static pthread_t msanGoSignalThread;
|
||||
|
||||
// msanGoSignalThreadSet is used to record that msanGoSignalThread
|
||||
// has been initialized. This is accessed atomically.
|
||||
static int32_t msanGoSignalThreadSet;
|
||||
|
||||
// uninit is explicitly poisoned, so that we can make all registers
|
||||
// undefined by calling msanGoWait.
|
||||
static unsigned long uninit;
|
||||
|
||||
// msanGoLoop loops calling msanGoWait, with the arguments passed
|
||||
// such that msan thinks that they are undefined. msan permits
|
||||
// undefined values to be used as long as they are not used to
|
||||
// for conditionals or for memory access.
|
||||
void msanGoLoop() {
|
||||
int i;
|
||||
|
||||
msanGoSignalThread = pthread_self();
|
||||
__atomic_store_n(&msanGoSignalThreadSet, 1, __ATOMIC_SEQ_CST);
|
||||
|
||||
// Force uninit to be undefined for msan.
|
||||
__msan_poison(&uninit, sizeof uninit);
|
||||
for (i = 0; i < 100; i++) {
|
||||
msanGoWait(uninit, uninit, uninit, uninit, uninit, uninit);
|
||||
}
|
||||
}
|
||||
|
||||
// msanGoReady returns whether msanGoSignalThread is set.
|
||||
int msanGoReady() {
|
||||
return __atomic_load_n(&msanGoSignalThreadSet, __ATOMIC_SEQ_CST) != 0;
|
||||
}
|
||||
|
||||
// msanGoSendSignal sends a signal to the msanGoLoop thread.
|
||||
void msanGoSendSignal() {
|
||||
pthread_kill(msanGoSignalThread, SIGWINCH);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.SetCgoTraceback(0, C.msanGoTraceback, nil, nil)
|
||||
|
||||
c := make(chan bool)
|
||||
go func() {
|
||||
defer func() { c <- true }()
|
||||
C.msanGoLoop()
|
||||
}()
|
||||
|
||||
for C.msanGoReady() == 0 {
|
||||
time.Sleep(time.Microsecond)
|
||||
}
|
||||
|
||||
loop:
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
break loop
|
||||
default:
|
||||
C.msanGoSendSignal()
|
||||
time.Sleep(time.Microsecond)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue