aboutsummaryrefslogtreecommitdiff
path: root/libgo/go
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-02-05 14:33:27 -0800
committerIan Lance Taylor <iant@golang.org>2020-02-15 09:14:10 -0800
commit0b3c2eed35d608d6541ecf004a9576b4eae0b4ef (patch)
treec92c05d53eb054d8085d069800f4e9b586fef5a3 /libgo/go
parent17edb3310d8ce9d5f6c9e53f6c1f7d611c2a5a41 (diff)
downloadgcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.zip
gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.tar.gz
gcc-0b3c2eed35d608d6541ecf004a9576b4eae0b4ef.tar.bz2
libgo: update to Go1.14rc1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/218017
Diffstat (limited to 'libgo/go')
-rw-r--r--libgo/go/cmd/go/alldocs.go16
-rw-r--r--libgo/go/cmd/go/go_test.go412
-rw-r--r--libgo/go/cmd/go/internal/clean/clean.go4
-rw-r--r--libgo/go/cmd/go/internal/list/list.go18
-rw-r--r--libgo/go/cmd/go/internal/modcmd/download.go4
-rw-r--r--libgo/go/cmd/go/internal/modfetch/cache.go18
-rw-r--r--libgo/go/cmd/go/internal/modfetch/codehost/git.go7
-rw-r--r--libgo/go/cmd/go/internal/modfetch/coderepo.go80
-rw-r--r--libgo/go/cmd/go/internal/modload/build.go2
-rw-r--r--libgo/go/cmd/go/internal/modload/help.go7
-rw-r--r--libgo/go/cmd/go/internal/modload/import.go9
-rw-r--r--libgo/go/cmd/go/internal/modload/load.go15
-rw-r--r--libgo/go/cmd/go/internal/modload/query.go2
-rw-r--r--libgo/go/cmd/go/internal/modload/query_test.go13
-rw-r--r--libgo/go/cmd/go/internal/work/gc.go4
-rw-r--r--libgo/go/cmd/go/testdata/badmod/go.mod1
-rw-r--r--libgo/go/cmd/go/testdata/badmod/x.go4
-rw-r--r--libgo/go/cmd/go/testdata/flag_test.go16
-rw-r--r--libgo/go/cmd/go/testdata/importcom/bad.go3
-rw-r--r--libgo/go/cmd/go/testdata/importcom/conflict.go3
-rw-r--r--libgo/go/cmd/go/testdata/importcom/src/bad/bad.go1
-rw-r--r--libgo/go/cmd/go/testdata/importcom/src/conflict/a.go1
-rw-r--r--libgo/go/cmd/go/testdata/importcom/src/conflict/b.go1
-rw-r--r--libgo/go/cmd/go/testdata/importcom/src/works/x/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go1
-rw-r--r--libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/importcom/works.go3
-rw-r--r--libgo/go/cmd/go/testdata/importcom/wrongplace.go3
-rw-r--r--libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go3
-rw-r--r--libgo/go/cmd/go/testdata/script/README2
-rw-r--r--libgo/go/cmd/go/testdata/script/clean_testcache.txt9
-rw-r--r--libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt4
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_get_test.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_load_badchain.txt2
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_readonly.txt5
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt57
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_replace_import.txt19
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_run_internal.txt46
-rw-r--r--libgo/go/cmd/go/testdata/script/mod_vendor.txt6
-rw-r--r--libgo/go/cmd/go/testdata/script/modfile_flag.txt9
-rw-r--r--libgo/go/cmd/go/testdata/script/test_badtest.txt19
-rw-r--r--libgo/go/cmd/go/testdata/src/badc/x.c1
-rw-r--r--libgo/go/cmd/go/testdata/src/badc/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/badpkg/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/bench/x_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/benchfatal/x_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/cgoasm/p.go8
-rw-r--r--libgo/go/cmd/go/testdata/src/cgoasm/p.s2
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover/p_test.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover2/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover2/x_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover3/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover3/p_test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover3/x_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover4/p.go19
-rw-r--r--libgo/go/cmd/go/testdata/src/cgocover4/x_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/dupload.go8
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/p/p.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/p2/p2.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/dupload/vendor/p/p.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/gencycle/gencycle.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/importmain/ismain/main.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/importmain/test/test.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/importmain/test/test_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/multimain/multimain_test.go16
-rw-r--r--libgo/go/cmd/go/testdata/src/not_main/not_main.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/notest/hello.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/run/bad.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/run/good.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/run/internal/internal.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/run/subdir/internal/private/private.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/sleepy1/p_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/sleepy2/p_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/sleepybad/p.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/syntaxerror/x.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go4
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go7
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go10
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/q1/q1.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/testcycle/q1/q1_test.go6
-rw-r--r--libgo/go/cmd/go/testdata/src/testdep/p1/p1.go1
-rw-r--r--libgo/go/cmd/go/testdata/src/testdep/p1/p1_test.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/testdep/p2/p2.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/testdep/p3/p3.go3
-rw-r--r--libgo/go/cmd/go/testdata/src/testnorun/p.go5
-rw-r--r--libgo/go/cmd/go/testdata/src/testrace/race_test.go31
-rw-r--r--libgo/go/cmd/go/testdata/src/testregexp/x_test.go17
-rw-r--r--libgo/go/cmd/go/testdata/src/testregexp/z_test.go19
-rw-r--r--libgo/go/crypto/tls/tls.go3
-rw-r--r--libgo/go/crypto/x509/root_cgo_darwin.go2
-rw-r--r--libgo/go/crypto/x509/root_windows.go20
-rw-r--r--libgo/go/database/sql/sql_test.go6
-rw-r--r--libgo/go/go/build/build_test.go46
-rw-r--r--libgo/go/go/build/deps_test.go2
-rw-r--r--libgo/go/go/doc/example.go2
-rw-r--r--libgo/go/go/types/builtins.go2
-rw-r--r--libgo/go/go/types/call.go2
-rw-r--r--libgo/go/go/types/lookup.go20
-rw-r--r--libgo/go/golang.org/x/crypto/cryptobyte/asn1.go5
-rw-r--r--libgo/go/golang.org/x/crypto/cryptobyte/string.go7
-rw-r--r--libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go2
-rw-r--r--libgo/go/golang.org/x/mod/sumdb/note/note.go3
-rw-r--r--libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go7
-rw-r--r--libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go2
-rw-r--r--libgo/go/html/escape.go2
-rw-r--r--libgo/go/internal/poll/fcntl_js.go14
-rw-r--r--libgo/go/internal/poll/fcntl_libc.go26
-rw-r--r--libgo/go/internal/poll/fcntl_syscall.go26
-rw-r--r--libgo/go/internal/poll/fd_fsync_darwin.go20
-rw-r--r--libgo/go/internal/poll/fd_fsync_posix.go15
-rw-r--r--libgo/go/internal/poll/fd_unix.go2
-rw-r--r--libgo/go/internal/syscall/unix/nonblocking.go2
-rw-r--r--libgo/go/internal/syscall/unix/nonblocking_libc.go (renamed from libgo/go/internal/syscall/unix/nonblocking_darwin.go)20
-rw-r--r--libgo/go/io/example_test.go7
-rw-r--r--libgo/go/math/big/arith_decl.go2
-rw-r--r--libgo/go/math/big/arith_decl_pure.go2
-rw-r--r--libgo/go/math/big/int.go5
-rw-r--r--libgo/go/net/dial_test.go2
-rw-r--r--libgo/go/net/dnsclient_unix_test.go2
-rw-r--r--libgo/go/net/http/cgi/integration_test.go (renamed from libgo/go/net/http/cgi/matryoshka_test.go)0
-rw-r--r--libgo/go/net/http/client.go17
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go8
-rw-r--r--libgo/go/net/http/omithttp2.go4
-rw-r--r--libgo/go/net/http/request.go12
-rw-r--r--libgo/go/net/http/transfer.go125
-rw-r--r--libgo/go/net/http/transfer_test.go284
-rw-r--r--libgo/go/net/http/transport.go27
-rw-r--r--libgo/go/net/http/transport_test.go70
-rw-r--r--libgo/go/net/lookup_test.go13
-rw-r--r--libgo/go/net/net.go1
-rw-r--r--libgo/go/os/file.go4
-rw-r--r--libgo/go/reflect/all_test.go21
-rw-r--r--libgo/go/reflect/type.go18
-rw-r--r--libgo/go/runtime/chan.go76
-rw-r--r--libgo/go/runtime/chan_test.go14
-rw-r--r--libgo/go/runtime/checkptr.go31
-rw-r--r--libgo/go/runtime/checkptr_test.go50
-rw-r--r--libgo/go/runtime/debug.go4
-rw-r--r--libgo/go/runtime/export_test.go4
-rw-r--r--libgo/go/runtime/extern.go28
-rw-r--r--libgo/go/runtime/gcinfo_test.go2
-rw-r--r--libgo/go/runtime/hash64.go2
-rw-r--r--libgo/go/runtime/lfstack_64bit.go2
-rw-r--r--libgo/go/runtime/malloc.go1
-rw-r--r--libgo/go/runtime/malloc_test.go8
-rw-r--r--libgo/go/runtime/memmove_test.go67
-rw-r--r--libgo/go/runtime/mgc.go15
-rw-r--r--libgo/go/runtime/mgcscavenge.go67
-rw-r--r--libgo/go/runtime/mgcscavenge_test.go28
-rw-r--r--libgo/go/runtime/mheap.go15
-rw-r--r--libgo/go/runtime/mkpreempt.go6
-rw-r--r--libgo/go/runtime/mpagealloc.go12
-rw-r--r--libgo/go/runtime/mpagealloc_64bit.go2
-rw-r--r--libgo/go/runtime/mpagealloc_test.go63
-rw-r--r--libgo/go/runtime/mpagecache_test.go6
-rw-r--r--libgo/go/runtime/mpallocbits.go10
-rw-r--r--libgo/go/runtime/mranges.go14
-rw-r--r--libgo/go/runtime/preempt_nonwindows.go13
-rw-r--r--libgo/go/runtime/proc.go117
-rw-r--r--libgo/go/runtime/runtime1.go2
-rw-r--r--libgo/go/runtime/runtime2.go13
-rw-r--r--libgo/go/runtime/sema.go6
-rw-r--r--libgo/go/runtime/signal_unix.go10
-rw-r--r--libgo/go/runtime/testdata/testprog/checkptr.go36
-rw-r--r--libgo/go/runtime/time.go239
-rw-r--r--libgo/go/runtime/trace.go17
-rw-r--r--libgo/go/runtime/trace/trace_stack_test.go1
-rw-r--r--libgo/go/runtime/utf8.go2
-rw-r--r--libgo/go/strconv/quote.go11
-rw-r--r--libgo/go/strings/strings.go20
-rw-r--r--libgo/go/syscall/syscall_aix.go4
-rw-r--r--libgo/go/testing/benchmark.go2
-rw-r--r--libgo/go/testing/panic_test.go129
-rw-r--r--libgo/go/testing/sub_test.go31
-rw-r--r--libgo/go/testing/testing.go55
-rw-r--r--libgo/go/text/template/exec_test.go3
-rw-r--r--libgo/go/text/template/funcs.go4
-rw-r--r--libgo/go/text/template/parse/lex.go1
-rw-r--r--libgo/go/time/format.go3
-rw-r--r--libgo/go/time/sleep_test.go2
-rw-r--r--libgo/go/time/time.go3
-rw-r--r--libgo/go/unicode/utf8/utf8.go2
187 files changed, 1514 insertions, 1816 deletions
diff --git a/libgo/go/cmd/go/alldocs.go b/libgo/go/cmd/go/alldocs.go
index 54e7a8b..971a756 100644
--- a/libgo/go/cmd/go/alldocs.go
+++ b/libgo/go/cmd/go/alldocs.go
@@ -907,7 +907,7 @@
// Main bool // is this the main module?
// Indirect bool // is this module only an indirect dependency of main module?
// Dir string // directory holding files for this module, if any
-// GoMod string // path to go.mod file for this module, if any
+// GoMod string // path to go.mod file used when loading this module, if any
// GoVersion string // go version used in module
// Error *ModuleError // error loading module
// }
@@ -916,6 +916,9 @@
// Err string // the error itself
// }
//
+// The file GoMod refers to may be outside the module directory if the
+// module is in the module cache or if the -modfile flag is used.
+//
// The default output is to print the module path and then
// information about the version and replacement if any.
// For example, 'go list -m all' might print:
@@ -1020,7 +1023,9 @@
// execution. The "go mod download" command is useful mainly for pre-filling
// the local cache or to compute the answers for a Go module proxy.
//
-// By default, download reports errors to standard error but is otherwise silent.
+// By default, download writes nothing to standard output. It may print progress
+// messages and errors to standard error.
+//
// The -json flag causes download to print a sequence of JSON objects
// to standard output, describing each downloaded module (or failure),
// corresponding to this Go struct:
@@ -2346,14 +2351,15 @@
//
// Module support
//
-// Go 1.13 includes support for Go modules. Module-aware mode is active by default
-// whenever a go.mod file is found in, or in a parent of, the current directory.
+// The go command includes support for Go modules. Module-aware mode is active
+// by default whenever a go.mod file is found in the current directory or in
+// any parent directory.
//
// The quickest way to take advantage of module support is to check out your
// repository, create a go.mod file (described in the next section) there, and run
// go commands from within that file tree.
//
-// For more fine-grained control, Go 1.13 continues to respect
+// For more fine-grained control, the go command continues to respect
// a temporary environment variable, GO111MODULE, which can be set to one
// of three string values: off, on, or auto (the default).
// If GO111MODULE=on, then the go command requires the use of modules,
diff --git a/libgo/go/cmd/go/go_test.go b/libgo/go/cmd/go/go_test.go
index ebd0c7a..d535ea0 100644
--- a/libgo/go/cmd/go/go_test.go
+++ b/libgo/go/cmd/go/go_test.go
@@ -638,7 +638,7 @@ func (tg *testgoData) grepStderrNot(match, msg string) {
}
// grepBothNot looks for a regular expression in the test run's
-// standard output or stand error and fails, logging msg, if it is
+// standard output or standard error and fails, logging msg, if it is
// found.
func (tg *testgoData) grepBothNot(match, msg string) {
tg.t.Helper()
@@ -913,6 +913,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
// Copy the runtime packages into a temporary GOROOT
// so that we can change files.
@@ -1026,28 +1027,6 @@ func TestInternalPackagesOutsideGOROOTAreRespected(t *testing.T) {
tg.grepBoth(`testinternal2(\/|\\)p\.go\:3\:8\: use of internal package .*internal/w not allowed`, "wrote error message for testdata/testinternal2")
}
-func TestRunInternal(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- dir := filepath.Join(tg.pwd(), "testdata")
- tg.setenv("GOPATH", dir)
- tg.run("run", filepath.Join(dir, "src/run/good.go"))
- tg.runFail("run", filepath.Join(dir, "src/run/bad.go"))
- tg.grepStderr(`testdata(\/|\\)src(\/|\\)run(\/|\\)bad\.go\:3\:8\: use of internal package run/subdir/internal/private not allowed`, "unexpected error for run/bad.go")
-}
-
-func TestRunPkg(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- dir := filepath.Join(tg.pwd(), "testdata")
- tg.setenv("GOPATH", dir)
- tg.run("run", "hello")
- tg.grepStderr("hello, world", "did not find hello, world")
- tg.cd(filepath.Join(dir, "src/hello"))
- tg.run("run", ".")
- tg.grepStderr("hello, world", "did not find hello, world")
-}
-
func TestInternalPackageErrorsAreHandled(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1062,56 +1041,6 @@ func TestInternalCache(t *testing.T) {
tg.grepStderr("internal", "did not fail to build p")
}
-func TestImportCommandMatch(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
- tg.run("build", "./testdata/importcom/works.go")
-}
-
-func TestImportCommentMismatch(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
- tg.runFail("build", "./testdata/importcom/wrongplace.go")
- tg.grepStderr(`wrongplace expects import "my/x"`, "go build did not mention incorrect import")
-}
-
-func TestImportCommentSyntaxError(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
- tg.runFail("build", "./testdata/importcom/bad.go")
- tg.grepStderr("cannot parse import comment", "go build did not mention syntax error")
-}
-
-func TestImportCommentConflict(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcom"))
- tg.runFail("build", "./testdata/importcom/conflict.go")
- tg.grepStderr("found import comments", "go build did not mention comment conflict")
-}
-
-func TestImportCycle(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata/importcycle"))
- tg.runFail("build", "selfimport")
-
- count := tg.grepCountBoth("import cycle not allowed")
- if count == 0 {
- t.Fatal("go build did not mention cyclical import")
- }
- if count > 1 {
- t.Fatal("go build mentioned import cycle more than once")
- }
-
- // Don't hang forever.
- tg.run("list", "-e", "-json", "selfimport")
-}
-
// cmd/go: custom import path checking should not apply to Go packages without import comment.
func TestIssue10952(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
@@ -1217,24 +1146,6 @@ func TestAccidentalGitCheckout(t *testing.T) {
}
}
-func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("test", "syntaxerror")
- tg.grepStderr("x_test.go:", "did not diagnose error")
- tg.grepStdout("FAIL", "go test did not say FAIL")
-}
-
-func TestWildcardsDoNotLookInUselessDirectories(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("list", "...")
- tg.grepBoth("badpkg", "go list ... failure does not mention badpkg")
- tg.run("list", "m...")
-}
-
func TestRelativeImportsGoTest(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -1673,6 +1584,7 @@ func TestDefaultGOPATHGet(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.setenv("GOPATH", "")
tg.tempDir("home")
tg.setenv(homeEnvName(), tg.path("home"))
@@ -1697,6 +1609,7 @@ func TestDefaultGOPATHGet(t *testing.T) {
func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.setenv("GOPATH", "")
tg.tempDir("home")
tg.setenv(homeEnvName(), tg.path("home"))
@@ -1819,16 +1732,6 @@ func TestGoTestMutexprofileDashOControlsBinaryLocation(t *testing.T) {
tg.wantExecutable("myerrors.test"+exeSuffix, "go test -mutexprofile -o myerrors.test did not create myerrors.test")
}
-func TestGoBuildNonMain(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("build", "-buildmode=exe", "-o", "not_main"+exeSuffix, "not_main")
- tg.grepStderr("-buildmode=exe requires exactly one main package", "go build with -o and -buildmode=exe should on a non-main package should throw an error")
- tg.mustNotExist("not_main" + exeSuffix)
-}
-
func TestGoTestDashCDashOControlsBinaryLocation(t *testing.T) {
skipIfGccgo(t, "gccgo has no standard packages")
tooSlow(t)
@@ -2192,33 +2095,6 @@ func TestCoverageNoStatements(t *testing.T) {
tg.grepStdout("[no statements]", "expected [no statements] for pkg4")
}
-func TestCoverageImportMainLoop(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("test", "importmain/test")
- tg.grepStderr("not an importable package", "did not detect import main")
- tg.runFail("test", "-cover", "importmain/test")
- tg.grepStderr("not an importable package", "did not detect import main")
-}
-
-func TestCoveragePattern(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.makeTempdir()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- // If coverpkg=sleepy... expands by package loading
- // (as opposed to pattern matching on deps)
- // then it will try to load sleepybad, which does not compile,
- // and the test command will fail.
- tg.run("test", "-coverprofile="+tg.path("cover.out"), "-coverpkg=sleepy...", "-run=^$", "sleepy1")
-}
-
func TestCoverageErrorLine(t *testing.T) {
skipIfGccgo(t, "gccgo has no cover tool")
tooSlow(t)
@@ -2291,20 +2167,6 @@ func TestCoverageDashC(t *testing.T) {
tg.wantExecutable(tg.path("coverdep"), "go -test -c -coverprofile did not create executable")
}
-func TestPluginNonMain(t *testing.T) {
- wd, err := os.Getwd()
- if err != nil {
- t.Fatal(err)
- }
-
- pkg := filepath.Join(wd, "testdata", "testdep", "p2")
-
- tg := testgo(t)
- defer tg.cleanup()
-
- tg.runFail("build", "-buildmode=plugin", pkg)
-}
-
func TestTestEmpty(t *testing.T) {
if !canRace {
t.Skip("no race detector")
@@ -2389,39 +2251,6 @@ func main() {
tg.grepStderrNot(`os.Stat .* no such file or directory`, "unexpected stat of archive file")
}
-func TestCoverageWithCgo(t *testing.T) {
- skipIfGccgo(t, "gccgo has no cover tool")
- tooSlow(t)
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
-
- for _, dir := range []string{"cgocover", "cgocover2", "cgocover3", "cgocover4"} {
- t.Run(dir, func(t *testing.T) {
- tg := testgo(t)
- tg.parallel()
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-short", "-cover", dir)
- data := tg.getStdout() + tg.getStderr()
- checkCoverage(tg, data)
- })
- }
-}
-
-func TestCgoAsmError(t *testing.T) {
- if !canCgo {
- t.Skip("skipping because cgo not enabled")
- }
-
- tg := testgo(t)
- tg.parallel()
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("build", "cgoasm")
- tg.grepBoth("package using cgo has Go assembly file", "did not detect Go assembly file")
-}
-
func TestCgoDependsOnSyscall(t *testing.T) {
if testing.Short() {
t.Skip("skipping test that removes $GOROOT/pkg/*_race in short mode")
@@ -2435,6 +2264,8 @@ func TestCgoDependsOnSyscall(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
+
files, err := filepath.Glob(filepath.Join(runtime.GOROOT(), "pkg", "*_race"))
tg.must(err)
for _, file := range files {
@@ -2648,14 +2479,6 @@ func TestListTemplateContextFunction(t *testing.T) {
}
}
-// cmd/go: "go test" should fail if package does not build
-func TestIssue7108(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("test", "notest")
-}
-
func TestGoBuildTestOnly(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -2677,17 +2500,6 @@ func TestGoBuildTestOnly(t *testing.T) {
tg.run("install", "./testonly...")
}
-func TestGoTestDetectsTestOnlyImportCycles(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("test", "-c", "testcycle/p3")
- tg.grepStderr("import cycle not allowed in test", "go test testcycle/p3 produced unexpected error")
-
- tg.runFail("test", "-c", "testcycle/q1")
- tg.grepStderr("import cycle not allowed in test", "go test testcycle/q1 produced unexpected error")
-}
-
func TestGoTestFooTestWorks(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -2715,29 +2527,6 @@ func TestGoTestMainAsNormalTest(t *testing.T) {
tg.grepBoth(okPattern, "go test did not say ok")
}
-func TestGoTestMainTwice(t *testing.T) {
- if testing.Short() {
- t.Skip("Skipping in short mode")
- }
- tg := testgo(t)
- defer tg.cleanup()
- tg.makeTempdir()
- tg.setenv("GOCACHE", tg.tempdir)
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-v", "multimain")
- if strings.Count(tg.getStdout(), "notwithstanding") != 2 {
- t.Fatal("tests did not run twice")
- }
-}
-
-func TestGoTestFlagsAfterPackage(t *testing.T) {
- tooSlow(t)
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "testdata/flag_test.go", "-v", "-args", "-v=7") // Two distinct -v flags.
- tg.run("test", "-v", "testdata/flag_test.go", "-args", "-v=7") // Two distinct -v flags.
-}
-
func TestGoTestXtestonlyWorks(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -2829,20 +2618,6 @@ func TestGoGenerateXTestPkgName(t *testing.T) {
}
}
-func TestGoGenerateBadImports(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("skipping because windows has no echo command")
- }
-
- // This package has an invalid import causing an import cycle,
- // but go generate is supposed to still run.
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("generate", "gencycle")
- tg.grepStdout("hello world", "go generate gencycle did not run generator")
-}
-
func TestGoGetCustomDomainWildcard(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
testenv.MustHaveExecPath(t, "git")
@@ -3268,43 +3043,6 @@ func TestGoTestRaceInstallCgo(t *testing.T) {
}
}
-func TestGoTestRaceFailures(t *testing.T) {
- tooSlow(t)
-
- if !canRace {
- t.Skip("skipping because race detector not supported")
- }
-
- tg := testgo(t)
- tg.parallel()
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- tg.run("test", "testrace")
-
- tg.runFail("test", "-race", "testrace")
- tg.grepStdout("FAIL: TestRace", "TestRace did not fail")
- tg.grepBothNot("PASS", "something passed")
-
- tg.runFail("test", "-race", "testrace", "-run", "XXX", "-bench", ".")
- tg.grepStdout("FAIL: BenchmarkRace", "BenchmarkRace did not fail")
- tg.grepBothNot("PASS", "something passed")
-}
-
-func TestGoTestImportErrorStack(t *testing.T) {
- const out = `package testdep/p1 (test)
- imports testdep/p2
- imports testdep/p3: build constraints exclude all Go files `
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("test", "testdep/p1")
- if !strings.Contains(tg.stderr.String(), out) {
- t.Fatalf("did not give full import stack:\n\n%s", tg.stderr.String())
- }
-}
-
func TestGoGetUpdate(t *testing.T) {
// golang.org/issue/9224.
// The recursive updating was trying to walk to
@@ -3627,27 +3365,6 @@ func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) {
tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
}
-// Issue 17119 more duplicate load errors
-func TestIssue17119(t *testing.T) {
- testenv.MustHaveExternalNetwork(t)
-
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("build", "dupload")
- tg.grepBothNot("duplicate load|internal error", "internal error")
-}
-
-func TestFatalInBenchmarkCauseNonZeroExitStatus(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.runFail("test", "-run", "^$", "-bench", ".", "./testdata/src/benchfatal")
- tg.grepBothNot("^ok", "test passed unexpectedly")
- tg.grepBoth("FAIL.*benchfatal", "test did not run everything")
-}
-
func TestBinaryOnlyPackages(t *testing.T) {
tooSlow(t)
@@ -3813,16 +3530,6 @@ func TestMatchesNoTests(t *testing.T) {
tg.grepBoth(noMatchesPattern, "go test did not say [no tests to run]")
}
-func TestMatchesNoTestsDoesNotOverrideBuildFailure(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.runFail("test", "-run", "ThisWillNotMatch", "syntaxerror")
- tg.grepBothNot(noMatchesPattern, "go test did say [no tests to run]")
- tg.grepBoth("FAIL", "go test did not say FAIL")
-}
-
func TestMatchesNoBenchmarksIsOK(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -3850,18 +3557,6 @@ func TestMatchesOnlyBenchmarkIsOK(t *testing.T) {
tg.grepBoth(okPattern, "go test did not say ok")
}
-func TestBenchmarkLabels(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- // TODO: tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-run", "^$", "-bench", ".", "bench")
- tg.grepStdout(`(?m)^goos: `+runtime.GOOS, "go test did not print goos")
- tg.grepStdout(`(?m)^goarch: `+runtime.GOARCH, "go test did not print goarch")
- tg.grepStdout(`(?m)^pkg: bench`, "go test did not say pkg: bench")
- tg.grepBothNot(`(?s)pkg:.*pkg:`, "go test said pkg multiple times")
-}
-
func TestBenchmarkLabelsOutsideGOPATH(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
@@ -4261,25 +3956,6 @@ func TestCgoFlagContainsSpace(t *testing.T) {
tg.grepStderrNot(`"-L[^"]+c flags".*"-L[^"]+c flags"`, "found too many quoted ld flags")
}
-// Issue #20435.
-func TestGoTestRaceCoverModeFailures(t *testing.T) {
- tooSlow(t)
- if !canRace {
- t.Skip("skipping because race detector not supported")
- }
-
- tg := testgo(t)
- tg.parallel()
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
-
- tg.run("test", "testrace")
-
- tg.runFail("test", "-race", "-covermode=set", "testrace")
- tg.grepStderr(`-covermode must be "atomic", not "set", when -race is enabled`, "-race -covermode=set was allowed")
- tg.grepBothNot("PASS", "something passed")
-}
-
// Issue 9737: verify that GOARM and GO386 affect the computed build ID.
func TestBuildIDContainsArchModeEnv(t *testing.T) {
if testing.Short() {
@@ -4319,60 +3995,6 @@ func main() {}`)
}))
}
-func TestTestRegexps(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "-cpu=1", "-run=X/Y", "-bench=X/Y", "-count=2", "-v", "testregexp")
- var lines []string
- for _, line := range strings.SplitAfter(tg.getStdout(), "\n") {
- if strings.Contains(line, "=== RUN") || strings.Contains(line, "--- BENCH") || strings.Contains(line, "LOG") {
- lines = append(lines, line)
- }
- }
-
- // Important parts:
- // TestX is run, twice
- // TestX/Y is run, twice
- // TestXX is run, twice
- // TestZ is not run
- // BenchmarkX is run but only with N=1, once
- // BenchmarkXX is run but only with N=1, once
- // BenchmarkX/Y is run in full, twice
- want := `=== RUN TestX
- TestX: x_test.go:6: LOG: X running
-=== RUN TestX/Y
- TestX/Y: x_test.go:8: LOG: Y running
-=== RUN TestXX
- TestXX: z_test.go:10: LOG: XX running
-=== RUN TestX
- TestX: x_test.go:6: LOG: X running
-=== RUN TestX/Y
- TestX/Y: x_test.go:8: LOG: Y running
-=== RUN TestXX
- TestXX: z_test.go:10: LOG: XX running
- BenchmarkX: x_test.go:13: LOG: X running N=1
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=1
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=100
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=10000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=100000000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=1
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=100
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=10000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=100000000
- BenchmarkX/Y: x_test.go:15: LOG: Y running N=1000000000
- BenchmarkXX: z_test.go:18: LOG: XX running N=1
-`
-
- have := strings.Join(lines, "")
- if have != want {
- t.Errorf("reduced output:<<<\n%s>>> want:<<<\n%s>>>", have, want)
- }
-}
-
func TestListTests(t *testing.T) {
tooSlow(t)
var tg *testgoData
@@ -4408,6 +4030,7 @@ func TestBuildmodePIE(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.tempFile("main.go", `package main; func main() { print("hello") }`)
src := tg.path("main.go")
@@ -4571,6 +4194,7 @@ func TestUpxCompression(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.tempFile("main.go", `package main; import "fmt"; func main() { fmt.Print("hello upx") }`)
src := tg.path("main.go")
@@ -4964,14 +4588,6 @@ func TestInstallDeps(t *testing.T) {
tg.mustExist(p1)
}
-func TestGoTestMinusN(t *testing.T) {
- // Intent here is to verify that 'go test -n' works without crashing.
- // This reuses flag_test.go, but really any test would do.
- tg := testgo(t)
- defer tg.cleanup()
- tg.run("test", "testdata/flag_test.go", "-n", "-args", "-v=7")
-}
-
func TestGoTestJSON(t *testing.T) {
skipIfGccgo(t, "gccgo does not have standard packages")
tooSlow(t)
@@ -5109,6 +4725,7 @@ func init() {}
func TestBadCommandLines(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.tempFile("src/x/x.go", "package x\n")
tg.setenv("GOPATH", tg.path("."))
@@ -5329,6 +4946,7 @@ func TestCgoCache(t *testing.T) {
func TestFilepathUnderCwdFormat(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
+ tg.parallel()
tg.run("test", "-x", "-cover", "log")
tg.grepStderrNot(`\.log\.cover\.go`, "-x output should contain correctly formatted filepath under cwd")
}
@@ -5433,16 +5051,6 @@ func TestCDAndGOPATHAreDifferent(t *testing.T) {
}
}
-// Issue 26242.
-func TestGoTestWithoutTests(t *testing.T) {
- tg := testgo(t)
- defer tg.cleanup()
- tg.parallel()
- tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
- tg.run("test", "testnorun")
- tg.grepStdout(`testnorun\t\[no test files\]`, "do not want test to run")
-}
-
// Issue 25579.
func TestGoBuildDashODevNull(t *testing.T) {
tooSlow(t)
diff --git a/libgo/go/cmd/go/internal/clean/clean.go b/libgo/go/cmd/go/internal/clean/clean.go
index 5f4bf4e..69e1748 100644
--- a/libgo/go/cmd/go/internal/clean/clean.go
+++ b/libgo/go/cmd/go/internal/clean/clean.go
@@ -178,7 +178,9 @@ func runClean(cmd *base.Command, args []string) {
}
}
if err != nil {
- base.Errorf("go clean -testcache: %v", err)
+ if _, statErr := os.Stat(dir); !os.IsNotExist(statErr) {
+ base.Errorf("go clean -testcache: %v", err)
+ }
}
}
}
diff --git a/libgo/go/cmd/go/internal/list/list.go b/libgo/go/cmd/go/internal/list/list.go
index b393c67..8d979e2 100644
--- a/libgo/go/cmd/go/internal/list/list.go
+++ b/libgo/go/cmd/go/internal/list/list.go
@@ -211,7 +211,7 @@ applied to a Go struct, but now a Module struct:
Main bool // is this the main module?
Indirect bool // is this module only an indirect dependency of main module?
Dir string // directory holding files for this module, if any
- GoMod string // path to go.mod file for this module, if any
+ GoMod string // path to go.mod file used when loading this module, if any
GoVersion string // go version used in module
Error *ModuleError // error loading module
}
@@ -220,6 +220,9 @@ applied to a Go struct, but now a Module struct:
Err string // the error itself
}
+The file GoMod refers to may be outside the module directory if the
+module is in the module cache or if the -modfile flag is used.
+
The default output is to print the module path and then
information about the version and replacement if any.
For example, 'go list -m all' might print:
@@ -387,15 +390,24 @@ func runList(cmd *base.Command, args []string) {
modload.InitMod() // Parses go.mod and sets cfg.BuildMod.
if cfg.BuildMod == "vendor" {
+ const actionDisabledFormat = "go list -m: can't %s using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)"
+
+ if *listVersions {
+ base.Fatalf(actionDisabledFormat, "determine available versions")
+ }
+ if *listU {
+ base.Fatalf(actionDisabledFormat, "determine available upgrades")
+ }
+
for _, arg := range args {
// In vendor mode, the module graph is incomplete: it contains only the
// explicit module dependencies and the modules that supply packages in
// the import graph. Reject queries that imply more information than that.
if arg == "all" {
- base.Fatalf("go list -m: can't compute 'all' using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
+ base.Fatalf(actionDisabledFormat, "compute 'all'")
}
if strings.Contains(arg, "...") {
- base.Fatalf("go list -m: can't match module patterns using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")
+ base.Fatalf(actionDisabledFormat, "match module patterns")
}
}
}
diff --git a/libgo/go/cmd/go/internal/modcmd/download.go b/libgo/go/cmd/go/internal/modcmd/download.go
index 5db0e46..7d5294d 100644
--- a/libgo/go/cmd/go/internal/modcmd/download.go
+++ b/libgo/go/cmd/go/internal/modcmd/download.go
@@ -30,7 +30,9 @@ The go command will automatically download modules as needed during ordinary
execution. The "go mod download" command is useful mainly for pre-filling
the local cache or to compute the answers for a Go module proxy.
-By default, download reports errors to standard error but is otherwise silent.
+By default, download writes nothing to standard output. It may print progress
+messages and errors to standard error.
+
The -json flag causes download to print a sequence of JSON objects
to standard output, describing each downloaded module (or failure),
corresponding to this Go struct:
diff --git a/libgo/go/cmd/go/internal/modfetch/cache.go b/libgo/go/cmd/go/internal/modfetch/cache.go
index 104fce8..947192b 100644
--- a/libgo/go/cmd/go/internal/modfetch/cache.go
+++ b/libgo/go/cmd/go/internal/modfetch/cache.go
@@ -13,7 +13,6 @@ import (
"os"
"path/filepath"
"strings"
- "time"
"cmd/go/internal/base"
"cmd/go/internal/cfg"
@@ -28,8 +27,6 @@ import (
var PkgMod string // $GOPATH/pkg/mod; set by package modload
-const logFindingDelay = 1 * time.Second
-
func cacheDir(path string) (string, error) {
if PkgMod == "" {
return "", fmt.Errorf("internal error: modfetch.PkgMod not set")
@@ -140,11 +137,6 @@ func (r *cachingRepo) Versions(prefix string) ([]string, error) {
err error
}
c := r.cache.Do("versions:"+prefix, func() interface{} {
- logTimer := time.AfterFunc(logFindingDelay, func() {
- fmt.Fprintf(os.Stderr, "go: finding versions for %s\n", r.path)
- })
- defer logTimer.Stop()
-
list, err := r.r.Versions(prefix)
return cached{list, err}
}).(cached)
@@ -167,11 +159,6 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) {
return cachedInfo{info, nil}
}
- logTimer := time.AfterFunc(logFindingDelay, func() {
- fmt.Fprintf(os.Stderr, "go: finding %s %s\n", r.path, rev)
- })
- defer logTimer.Stop()
-
info, err = r.r.Stat(rev)
if err == nil {
// If we resolved, say, 1234abcde to v0.0.0-20180604122334-1234abcdef78,
@@ -199,11 +186,6 @@ func (r *cachingRepo) Stat(rev string) (*RevInfo, error) {
func (r *cachingRepo) Latest() (*RevInfo, error) {
c := r.cache.Do("latest:", func() interface{} {
- logTimer := time.AfterFunc(logFindingDelay, func() {
- fmt.Fprintf(os.Stderr, "go: finding %s latest\n", r.path)
- })
- defer logTimer.Stop()
-
info, err := r.r.Latest()
// Save info for likely future Stat call.
diff --git a/libgo/go/cmd/go/internal/modfetch/codehost/git.go b/libgo/go/cmd/go/internal/modfetch/codehost/git.go
index e329cbc..f08df51 100644
--- a/libgo/go/cmd/go/internal/modfetch/codehost/git.go
+++ b/libgo/go/cmd/go/internal/modfetch/codehost/git.go
@@ -682,8 +682,11 @@ func (r *gitRepo) RecentTag(rev, prefix, major string) (tag string, err error) {
semtag := line[len(prefix):]
// Consider only tags that are valid and complete (not just major.minor prefixes).
- if c := semver.Canonical(semtag); c != "" && strings.HasPrefix(semtag, c) && (major == "" || semver.Major(c) == major) {
- highest = semver.Max(highest, semtag)
+ // NOTE: Do not replace the call to semver.Compare with semver.Max.
+ // We want to return the actual tag, not a canonicalized version of it,
+ // and semver.Max currently canonicalizes (see golang.org/issue/32700).
+ if c := semver.Canonical(semtag); c != "" && strings.HasPrefix(semtag, c) && (major == "" || semver.Major(c) == major) && semver.Compare(semtag, highest) > 0 {
+ highest = semtag
}
}
diff --git a/libgo/go/cmd/go/internal/modfetch/coderepo.go b/libgo/go/cmd/go/internal/modfetch/coderepo.go
index de757ec..d1d24a40 100644
--- a/libgo/go/cmd/go/internal/modfetch/coderepo.go
+++ b/libgo/go/cmd/go/internal/modfetch/coderepo.go
@@ -191,22 +191,6 @@ func (r *codeRepo) appendIncompatibleVersions(list, incompatible []string) ([]st
return list, nil
}
- // We assume that if the latest release of any major version has a go.mod
- // file, all subsequent major versions will also have go.mod files (and thus
- // be ineligible for use as +incompatible versions).
- // If we're wrong about a major version, users will still be able to 'go get'
- // specific higher versions explicitly — they just won't affect 'latest' or
- // appear in 'go list'.
- //
- // Conversely, we assume that if the latest release of any major version lacks
- // a go.mod file, all versions also lack go.mod files. If we're wrong, we may
- // include a +incompatible version that isn't really valid, but most
- // operations won't try to use that version anyway.
- //
- // These optimizations bring
- // 'go list -versions -m github.com/openshift/origin' down from 1m58s to 0m37s.
- // That's still not great, but a substantial improvement.
-
versionHasGoMod := func(v string) (bool, error) {
_, err := r.code.ReadFile(v, "go.mod", codehost.MaxGoMod)
if err == nil {
@@ -241,32 +225,41 @@ func (r *codeRepo) appendIncompatibleVersions(list, incompatible []string) ([]st
}
}
- var lastMajor string
+ var (
+ lastMajor string
+ lastMajorHasGoMod bool
+ )
for i, v := range incompatible {
major := semver.Major(v)
- if major == lastMajor {
- list = append(list, v+"+incompatible")
- continue
- }
- rem := incompatible[i:]
- j := sort.Search(len(rem), func(j int) bool {
- return semver.Major(rem[j]) != major
- })
- latestAtMajor := rem[j-1]
-
- ok, err := versionHasGoMod(latestAtMajor)
- if err != nil {
- return nil, err
- }
- if ok {
- // This major version has a go.mod file, so it is not allowed as
- // +incompatible. Subsequent major versions are likely to also have
- // go.mod files, so stop here.
- break
+ if major != lastMajor {
+ rem := incompatible[i:]
+ j := sort.Search(len(rem), func(j int) bool {
+ return semver.Major(rem[j]) != major
+ })
+ latestAtMajor := rem[j-1]
+
+ var err error
+ lastMajor = major
+ lastMajorHasGoMod, err = versionHasGoMod(latestAtMajor)
+ if err != nil {
+ return nil, err
+ }
}
- lastMajor = major
+ if lastMajorHasGoMod {
+ // The latest release of this major version has a go.mod file, so it is
+ // not allowed as +incompatible. It would be confusing to include some
+ // minor versions of this major version as +incompatible but require
+ // semantic import versioning for others, so drop all +incompatible
+ // versions for this major version.
+ //
+ // If we're wrong about a minor version in the middle, users will still be
+ // able to 'go get' specific tags for that version explicitly — they just
+ // won't appear in 'go list' or as the results for queries with inequality
+ // bounds.
+ continue
+ }
list = append(list, v+"+incompatible")
}
@@ -708,7 +701,7 @@ func (r *codeRepo) findDir(version string) (rev, dir string, gomod []byte, err e
return "", "", nil, fmt.Errorf("reading %s/%s at revision %s: %v", r.pathPrefix, file1, rev, err1)
}
mpath1 := modfile.ModulePath(gomod1)
- found1 := err1 == nil && isMajor(mpath1, r.pathMajor)
+ found1 := err1 == nil && (isMajor(mpath1, r.pathMajor) || r.canReplaceMismatchedVersionDueToBug(mpath1))
var file2 string
if r.pathMajor != "" && r.codeRoot != r.modPath && !strings.HasPrefix(r.pathMajor, ".") {
@@ -817,6 +810,17 @@ func isMajor(mpath, pathMajor string) bool {
return pathMajor[1:] == mpathMajor[1:]
}
+// canReplaceMismatchedVersionDueToBug reports whether versions of r
+// could replace versions of mpath with otherwise-mismatched major versions
+// due to a historical bug in the Go command (golang.org/issue/34254).
+func (r *codeRepo) canReplaceMismatchedVersionDueToBug(mpath string) bool {
+ // The bug caused us to erroneously accept unversioned paths as replacements
+ // for versioned gopkg.in paths.
+ unversioned := r.pathMajor == ""
+ replacingGopkgIn := strings.HasPrefix(mpath, "gopkg.in/")
+ return unversioned && replacingGopkgIn
+}
+
func (r *codeRepo) GoMod(version string) (data []byte, err error) {
if version != module.CanonicalVersion(version) {
return nil, fmt.Errorf("version %s is not canonical", version)
diff --git a/libgo/go/cmd/go/internal/modload/build.go b/libgo/go/cmd/go/internal/modload/build.go
index 292fd45..d0642bc 100644
--- a/libgo/go/cmd/go/internal/modload/build.go
+++ b/libgo/go/cmd/go/internal/modload/build.go
@@ -112,7 +112,7 @@ func moduleInfo(m module.Version, fromBuildList bool) *modinfo.ModulePublic {
}
if HasModRoot() {
info.Dir = ModRoot()
- info.GoMod = filepath.Join(info.Dir, "go.mod")
+ info.GoMod = ModFilePath()
if modFile.Go != nil {
info.GoVersion = modFile.Go.Version
}
diff --git a/libgo/go/cmd/go/internal/modload/help.go b/libgo/go/cmd/go/internal/modload/help.go
index b47f3de..66c1f70 100644
--- a/libgo/go/cmd/go/internal/modload/help.go
+++ b/libgo/go/cmd/go/internal/modload/help.go
@@ -21,14 +21,15 @@ which source files are used in a given build.
Module support
-Go 1.13 includes support for Go modules. Module-aware mode is active by default
-whenever a go.mod file is found in, or in a parent of, the current directory.
+The go command includes support for Go modules. Module-aware mode is active
+by default whenever a go.mod file is found in the current directory or in
+any parent directory.
The quickest way to take advantage of module support is to check out your
repository, create a go.mod file (described in the next section) there, and run
go commands from within that file tree.
-For more fine-grained control, Go 1.13 continues to respect
+For more fine-grained control, the go command continues to respect
a temporary environment variable, GO111MODULE, which can be set to one
of three string values: off, on, or auto (the default).
If GO111MODULE=on, then the go command requires the use of modules,
diff --git a/libgo/go/cmd/go/internal/modload/import.go b/libgo/go/cmd/go/internal/modload/import.go
index 9ae2900..5906d64 100644
--- a/libgo/go/cmd/go/internal/modload/import.go
+++ b/libgo/go/cmd/go/internal/modload/import.go
@@ -203,7 +203,12 @@ func Import(path string) (m module.Version, dir string, err error) {
latest := map[string]string{} // path -> version
for _, r := range modFile.Replace {
if maybeInModule(path, r.Old.Path) {
- latest[r.Old.Path] = semver.Max(r.Old.Version, latest[r.Old.Path])
+ // Don't use semver.Max here; need to preserve +incompatible suffix.
+ v := latest[r.Old.Path]
+ if semver.Compare(r.Old.Version, v) > 0 {
+ v = r.Old.Version
+ }
+ latest[r.Old.Path] = v
}
}
@@ -264,6 +269,8 @@ func Import(path string) (m module.Version, dir string, err error) {
return module.Version{}, "", &ImportMissingError{Path: path}
}
+ fmt.Fprintf(os.Stderr, "go: finding module for package %s\n", path)
+
candidates, err := QueryPackage(path, "latest", Allowed)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
diff --git a/libgo/go/cmd/go/internal/modload/load.go b/libgo/go/cmd/go/internal/modload/load.go
index 408c790..7a8391d 100644
--- a/libgo/go/cmd/go/internal/modload/load.go
+++ b/libgo/go/cmd/go/internal/modload/load.go
@@ -1324,6 +1324,21 @@ func fetch(mod module.Version) (dir string, isLocal bool, err error) {
if !filepath.IsAbs(dir) {
dir = filepath.Join(ModRoot(), dir)
}
+ // Ensure that the replacement directory actually exists:
+ // dirInModule does not report errors for missing modules,
+ // so if we don't report the error now, later failures will be
+ // very mysterious.
+ if _, err := os.Stat(dir); err != nil {
+ if os.IsNotExist(err) {
+ // Semantically the module version itself “exists” — we just don't
+ // have its source code. Remove the equivalence to os.ErrNotExist,
+ // and make the message more concise while we're at it.
+ err = fmt.Errorf("replacement directory %s does not exist", r.Path)
+ } else {
+ err = fmt.Errorf("replacement directory %s: %w", r.Path, err)
+ }
+ return dir, true, module.VersionError(mod, err)
+ }
return dir, true, nil
}
mod = r
diff --git a/libgo/go/cmd/go/internal/modload/query.go b/libgo/go/cmd/go/internal/modload/query.go
index 53278b9..031e459 100644
--- a/libgo/go/cmd/go/internal/modload/query.go
+++ b/libgo/go/cmd/go/internal/modload/query.go
@@ -79,7 +79,7 @@ func queryProxy(proxy, path, query, current string, allowed func(module.Version)
if current != "" && !semver.IsValid(current) {
return nil, fmt.Errorf("invalid previous version %q", current)
}
- if cfg.BuildMod != "" && cfg.BuildMod != "mod" {
+ if cfg.BuildMod == "vendor" {
return nil, errQueryDisabled
}
if allowed == nil {
diff --git a/libgo/go/cmd/go/internal/modload/query_test.go b/libgo/go/cmd/go/internal/modload/query_test.go
index 9c91c05..15470e2 100644
--- a/libgo/go/cmd/go/internal/modload/query_test.go
+++ b/libgo/go/cmd/go/internal/modload/query_test.go
@@ -64,7 +64,7 @@ var queryTests = []struct {
git add go.mod
git commit -m v1 go.mod
git tag start
- for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata; do
+ for i in v0.0.0-pre1 v0.0.0 v0.0.1 v0.0.2 v0.0.3 v0.1.0 v0.1.1 v0.1.2 v0.3.0 v1.0.0 v1.1.0 v1.9.0 v1.9.9 v1.9.10-pre1 v1.9.10-pre2+metadata unversioned; do
echo before $i >status
git add status
git commit -m "before $i" status
@@ -107,6 +107,7 @@ var queryTests = []struct {
{path: queryRepo, query: "v0.2", err: `no matching versions for query "v0.2"`},
{path: queryRepo, query: "v0.0", vers: "v0.0.3"},
{path: queryRepo, query: "v1.9.10-pre2+metadata", vers: "v1.9.10-pre2.0.20190513201126-42abcb6df8ee"},
+ {path: queryRepo, query: "ed5ffdaa", vers: "v1.9.10-pre2.0.20191220134614-ed5ffdaa1f5e"},
// golang.org/issue/29262: The major version for for a module without a suffix
// should be based on the most recent tag (v1 as appropriate, not v0
@@ -162,10 +163,14 @@ var queryTests = []struct {
{path: queryRepoV2, query: "v2.6.0-pre1", vers: "v2.6.0-pre1"},
{path: queryRepoV2, query: "latest", vers: "v2.5.5"},
- // e0cf3de987e6 is the latest commit on the master branch, and it's actually
- // v1.19.10-pre1, not anything resembling v3: attempting to query it as such
- // should fail.
+ // Commit e0cf3de987e6 is actually v1.19.10-pre1, not anything resembling v3,
+ // and it has a go.mod file with a non-v3 module path. Attempting to query it
+ // as the v3 module should fail.
{path: queryRepoV3, query: "e0cf3de987e6", err: `vcs-test.golang.org/git/querytest.git/v3@v3.0.0-20180704024501-e0cf3de987e6: invalid version: go.mod has non-.../v3 module path "vcs-test.golang.org/git/querytest.git" (and .../v3/go.mod does not exist) at revision e0cf3de987e6`},
+
+ // The querytest repo does not have any commits tagged with major version 3,
+ // and the latest commit in the repo has a go.mod file specifying a non-v3 path.
+ // That should prevent us from resolving any version for the /v3 path.
{path: queryRepoV3, query: "latest", err: `no matching versions for query "latest"`},
{path: emptyRepo, query: "latest", vers: "v0.0.0-20180704023549-7bb914627242"},
diff --git a/libgo/go/cmd/go/internal/work/gc.go b/libgo/go/cmd/go/internal/work/gc.go
index 5702469..7d17c0c 100644
--- a/libgo/go/cmd/go/internal/work/gc.go
+++ b/libgo/go/cmd/go/internal/work/gc.go
@@ -227,8 +227,8 @@ func (a *Action) trimpath() string {
// For "go build -trimpath", rewrite package source directory
// to a file system-independent path (just the import path).
if cfg.BuildTrimpath {
- if m := a.Package.Module; m != nil {
- rewrite += ";" + m.Dir + "=>" + m.Path + "@" + m.Version
+ if m := a.Package.Module; m != nil && m.Version != "" {
+ rewrite += ";" + a.Package.Dir + "=>" + m.Path + "@" + m.Version + strings.TrimPrefix(a.Package.ImportPath, m.Path)
} else {
rewrite += ";" + a.Package.Dir + "=>" + a.Package.ImportPath
}
diff --git a/libgo/go/cmd/go/testdata/badmod/go.mod b/libgo/go/cmd/go/testdata/badmod/go.mod
deleted file mode 100644
index f7f6423..0000000
--- a/libgo/go/cmd/go/testdata/badmod/go.mod
+++ /dev/null
@@ -1 +0,0 @@
-module m
diff --git a/libgo/go/cmd/go/testdata/badmod/x.go b/libgo/go/cmd/go/testdata/badmod/x.go
deleted file mode 100644
index 579fb08..0000000
--- a/libgo/go/cmd/go/testdata/badmod/x.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package x
-
-import _ "appengine"
-import _ "nonexistent.rsc.io" // domain does not exist
diff --git a/libgo/go/cmd/go/testdata/flag_test.go b/libgo/go/cmd/go/testdata/flag_test.go
deleted file mode 100644
index ddf613d..0000000
--- a/libgo/go/cmd/go/testdata/flag_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package flag_test
-
-import (
- "flag"
- "log"
- "testing"
-)
-
-var v = flag.Int("v", 0, "v flag")
-
-// Run this as go test pkg -v=7
-func TestVFlagIsSet(t *testing.T) {
- if *v != 7 {
- log.Fatal("v flag not set")
- }
-}
diff --git a/libgo/go/cmd/go/testdata/importcom/bad.go b/libgo/go/cmd/go/testdata/importcom/bad.go
deleted file mode 100644
index e104c2e..0000000
--- a/libgo/go/cmd/go/testdata/importcom/bad.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import "bad"
diff --git a/libgo/go/cmd/go/testdata/importcom/conflict.go b/libgo/go/cmd/go/testdata/importcom/conflict.go
deleted file mode 100644
index 995556c..0000000
--- a/libgo/go/cmd/go/testdata/importcom/conflict.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import "conflict"
diff --git a/libgo/go/cmd/go/testdata/importcom/src/bad/bad.go b/libgo/go/cmd/go/testdata/importcom/src/bad/bad.go
deleted file mode 100644
index bc51fd3..0000000
--- a/libgo/go/cmd/go/testdata/importcom/src/bad/bad.go
+++ /dev/null
@@ -1 +0,0 @@
-package bad // import
diff --git a/libgo/go/cmd/go/testdata/importcom/src/conflict/a.go b/libgo/go/cmd/go/testdata/importcom/src/conflict/a.go
deleted file mode 100644
index 2d67703..0000000
--- a/libgo/go/cmd/go/testdata/importcom/src/conflict/a.go
+++ /dev/null
@@ -1 +0,0 @@
-package conflict // import "a"
diff --git a/libgo/go/cmd/go/testdata/importcom/src/conflict/b.go b/libgo/go/cmd/go/testdata/importcom/src/conflict/b.go
deleted file mode 100644
index 8fcfb3c..0000000
--- a/libgo/go/cmd/go/testdata/importcom/src/conflict/b.go
+++ /dev/null
@@ -1 +0,0 @@
-package conflict /* import "b" */
diff --git a/libgo/go/cmd/go/testdata/importcom/src/works/x/x.go b/libgo/go/cmd/go/testdata/importcom/src/works/x/x.go
deleted file mode 100644
index 044c6ec..0000000
--- a/libgo/go/cmd/go/testdata/importcom/src/works/x/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package x // import "works/x"
diff --git a/libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go b/libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go
deleted file mode 100644
index 2449b29..0000000
--- a/libgo/go/cmd/go/testdata/importcom/src/works/x/x1.go
+++ /dev/null
@@ -1 +0,0 @@
-package x // important! not an import comment
diff --git a/libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go b/libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go
deleted file mode 100644
index b89849d..0000000
--- a/libgo/go/cmd/go/testdata/importcom/src/wrongplace/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package x // import "my/x"
diff --git a/libgo/go/cmd/go/testdata/importcom/works.go b/libgo/go/cmd/go/testdata/importcom/works.go
deleted file mode 100644
index 31b55d0..0000000
--- a/libgo/go/cmd/go/testdata/importcom/works.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import _ "works/x"
diff --git a/libgo/go/cmd/go/testdata/importcom/wrongplace.go b/libgo/go/cmd/go/testdata/importcom/wrongplace.go
deleted file mode 100644
index e2535e0..0000000
--- a/libgo/go/cmd/go/testdata/importcom/wrongplace.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p
-
-import "wrongplace"
diff --git a/libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go b/libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go
deleted file mode 100644
index dc63c4b..0000000
--- a/libgo/go/cmd/go/testdata/importcycle/src/selfimport/selfimport.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package selfimport
-
-import "selfimport"
diff --git a/libgo/go/cmd/go/testdata/script/README b/libgo/go/cmd/go/testdata/script/README
index 2782a09..7dba6b3 100644
--- a/libgo/go/cmd/go/testdata/script/README
+++ b/libgo/go/cmd/go/testdata/script/README
@@ -40,7 +40,7 @@ Scripts also have access to these other environment variables:
goversion=<current Go version; for example, 1.12>
:=<OS-specific path list separator>
-The scripts supporting files are unpacked relative to $GOPATH/src (aka $WORK/gopath/src)
+The scripts' supporting files are unpacked relative to $GOPATH/src (aka $WORK/gopath/src)
and then the script begins execution in that directory as well. Thus the example above runs
in $WORK/gopath/src with GOPATH=$WORK/gopath and $WORK/gopath/src/hello.go
containing the listed contents.
diff --git a/libgo/go/cmd/go/testdata/script/clean_testcache.txt b/libgo/go/cmd/go/testdata/script/clean_testcache.txt
index dd78464..b3f32fe 100644
--- a/libgo/go/cmd/go/testdata/script/clean_testcache.txt
+++ b/libgo/go/cmd/go/testdata/script/clean_testcache.txt
@@ -9,6 +9,13 @@ go clean -testcache
go test x_test.go
! stdout 'cached'
+# golang.org/issue/29100: 'go clean -testcache' should succeed
+# if the cache directory doesn't exist at all.
+# It should not write a testexpire.txt file, since there are no
+# test results that need to be invalidated in the first place.
+env GOCACHE=$WORK/nonexistent
+go clean -testcache
+! exists $WORK/nonexistent
-- x/x_test.go --
package x_test
@@ -16,4 +23,4 @@ import (
"testing"
)
func TestMain(t *testing.T) {
-} \ No newline at end of file
+}
diff --git a/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt b/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
index c2ca27a..03169bf 100644
--- a/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
+++ b/libgo/go/cmd/go/testdata/script/link_syso_issue33139.txt
@@ -8,6 +8,10 @@
# See: https://github.com/golang/go/issues/8912
[linux] [ppc64] skip
+# External linking is not supported on linux/riscv64.
+# See: https://github.com/golang/go/issues/36739
+[linux] [riscv64] skip
+
# External linking is not supported on darwin/386 (10.14+).
# See: https://github.com/golang/go/issues/31751
[darwin] [386] skip
diff --git a/libgo/go/cmd/go/testdata/script/mod_get_test.txt b/libgo/go/cmd/go/testdata/script/mod_get_test.txt
index f921168..3680ca2 100644
--- a/libgo/go/cmd/go/testdata/script/mod_get_test.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_get_test.txt
@@ -33,7 +33,7 @@ grep 'rsc.io/quote v1.5.1$' go.mod
# 'go get all' should consider test dependencies with or without -t.
cp go.mod.empty go.mod
-go get all
+go get -d all
grep 'rsc.io/quote v1.5.2$' go.mod
-- go.mod.empty --
diff --git a/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt b/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt
index 2c532f1..67d9a15 100644
--- a/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_load_badchain.txt
@@ -75,12 +75,14 @@ go: example.com/badchain/a@v1.1.0 requires
module declares its path as: badchain.example.com/c
but was required as: example.com/badchain/c
-- list-missing-expected --
+go: finding module for package example.com/badchain/c
go: found example.com/badchain/c in example.com/badchain/c v1.1.0
go: m/use imports
example.com/badchain/c: example.com/badchain/c@v1.1.0: parsing go.mod:
module declares its path as: badchain.example.com/c
but was required as: example.com/badchain/c
-- list-missing-test-expected --
+go: finding module for package example.com/badchain/c
go: found example.com/badchain/c in example.com/badchain/c v1.1.0
go: m/testuse tested by
m/testuse.test imports
diff --git a/libgo/go/cmd/go/testdata/script/mod_readonly.txt b/libgo/go/cmd/go/testdata/script/mod_readonly.txt
index 1d1771e..77fc735 100644
--- a/libgo/go/cmd/go/testdata/script/mod_readonly.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_readonly.txt
@@ -34,6 +34,11 @@ go list all
go clean -modcache
go list all
+# -mod=readonly must not cause 'go list -m' to fail.
+# (golang.org/issue/36478)
+go list -m all
+! stderr 'cannot query module'
+
# -mod=readonly should reject inconsistent go.mod files
# (ones that would be rewritten).
go mod edit -require rsc.io/sampler@v1.2.0
diff --git a/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt b/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt
index 6608fb1..28c1196 100644
--- a/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_replace_gopkgin.txt
@@ -15,10 +15,28 @@ env GOSUMDB=off
# Replacing gopkg.in/[…].vN with a repository with a root go.mod file
# specifying […].vN and a compatible version should succeed, even if
# the replacement path is not a gopkg.in path.
-cd dot-to-dot
-go list gopkg.in/src-d/go-git.v4
+cd 4-to-4
+go list -m gopkg.in/src-d/go-git.v4
--- dot-to-dot/go.mod --
+# Previous versions of the "go" command accepted v0 and v1 pseudo-versions
+# as replacements for gopkg.in/[…].v4.
+# As a special case, we continue to accept those.
+
+cd ../4-to-0
+go list -m gopkg.in/src-d/go-git.v4
+
+cd ../4-to-1
+go list -m gopkg.in/src-d/go-git.v4
+
+cd ../4-to-incompatible
+go list -m gopkg.in/src-d/go-git.v4
+
+# A mismatched gopkg.in path should not be able to replace a different major version.
+cd ../3-to-gomod-4
+! go list -m gopkg.in/src-d/go-git.v3
+stderr '^go: gopkg\.in/src-d/go-git\.v3@v3.0.0-20190801152248-0d1a009cbb60: invalid version: go\.mod has non-\.\.\.\.v3 module path "gopkg\.in/src-d/go-git\.v4" at revision 0d1a009cbb60$'
+
+-- 4-to-4/go.mod --
module golang.org/issue/34254
go 1.13
@@ -26,3 +44,36 @@ go 1.13
require gopkg.in/src-d/go-git.v4 v4.13.1
replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git/v4 v4.13.1
+-- 4-to-1/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git v1.0.1-0.20190801152248-0d1a009cbb60
+-- 4-to-0/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git v0.0.0-20190801152248-0d1a009cbb60
+-- 4-to-incompatible/go.mod --
+module golang.org/issue/34254
+
+go 1.13
+
+require gopkg.in/src-d/go-git.v4 v4.13.1
+
+replace gopkg.in/src-d/go-git.v4 v4.13.1 => github.com/src-d/go-git v4.6.0+incompatible
+-- 3-to-gomod-4/go.mod --
+module golang.org/issue/34254
+go 1.13
+
+require gopkg.in/src-d/go-git.v3 v3.2.0
+
+// This replacement has a go.mod file declaring its path to be
+// gopkg.in/src-d/go-git.v4, so it cannot be used as a replacement for v3.
+replace gopkg.in/src-d/go-git.v3 v3.2.0 => gopkg.in/src-d/go-git.v3 v3.0.0-20190801152248-0d1a009cbb60
diff --git a/libgo/go/cmd/go/testdata/script/mod_replace_import.txt b/libgo/go/cmd/go/testdata/script/mod_replace_import.txt
index 941ef61..fd5b04a 100644
--- a/libgo/go/cmd/go/testdata/script/mod_replace_import.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_replace_import.txt
@@ -28,7 +28,8 @@ stdout 'example.com/v v1.12.0 => ./v12'
cd fail
! go list all
stdout 'localhost.fail'
-stderr '^can.t load package: m.go:3:8: module w@latest found \(v0.0.0-00010101000000-000000000000, replaced by ../w\), but does not contain package w$'
+stderr '^can''t load package: m.go:4:2: module w@latest found \(v0.0.0-00010101000000-000000000000, replaced by ../w\), but does not contain package w$'
+stderr '^can''t load package: m.go:5:2: nonexist@v0.1.0: replacement directory ../nonexist does not exist$'
-- go.mod --
module example.com/m
@@ -54,6 +55,10 @@ replace (
example.com/v => ./v
)
+replace (
+ example.com/i v2.0.0+incompatible => ./i2
+)
+
-- m.go --
package main
import (
@@ -61,6 +66,7 @@ import (
_ "example.com/x/v3"
_ "example.com/y/z/w"
_ "example.com/v"
+ _ "example.com/i"
)
func main() {}
@@ -115,10 +121,18 @@ module v.localhost
-- v/v.go --
package v
+-- i2/go.mod --
+module example.com/i
+-- i2/i.go --
+package i
+
-- fail/m.go --
package main
-import _ "w"
+import (
+ _ "w"
+ _ "nonexist"
+)
func main() {}
@@ -127,3 +141,4 @@ module localhost.fail
replace w => ../w
+replace nonexist v0.1.0 => ../nonexist
diff --git a/libgo/go/cmd/go/testdata/script/mod_run_internal.txt b/libgo/go/cmd/go/testdata/script/mod_run_internal.txt
deleted file mode 100644
index 653ad28..0000000
--- a/libgo/go/cmd/go/testdata/script/mod_run_internal.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-env GO111MODULE=on
-
-go list -e -f '{{.Incomplete}}' runbad1.go
-stdout true
-! go run runbad1.go
-stderr 'use of internal package m/x/internal not allowed'
-
-go list -e -f '{{.Incomplete}}' runbad2.go
-stdout true
-! go run runbad2.go
-stderr 'use of internal package m/x/internal/y not allowed'
-
-go list -e -f '{{.Incomplete}}' runok.go
-stdout false
-go run runok.go
-
--- go.mod --
-module m
-
--- x/internal/internal.go --
-package internal
-
--- x/internal/y/y.go --
-package y
-
--- internal/internal.go --
-package internal
-
--- internal/z/z.go --
-package z
-
--- runbad1.go --
-package main
-import _ "m/x/internal"
-func main() {}
-
--- runbad2.go --
-package main
-import _ "m/x/internal/y"
-func main() {}
-
--- runok.go --
-package main
-import _ "m/internal"
-import _ "m/internal/z"
-func main() {}
diff --git a/libgo/go/cmd/go/testdata/script/mod_vendor.txt b/libgo/go/cmd/go/testdata/script/mod_vendor.txt
index bb3e634..2622916 100644
--- a/libgo/go/cmd/go/testdata/script/mod_vendor.txt
+++ b/libgo/go/cmd/go/testdata/script/mod_vendor.txt
@@ -38,6 +38,12 @@ stdout 'src[\\/]vendor[\\/]x'
go list -mod=vendor -f '{{.Version}} {{.Dir}}' -m x
stdout '^v1.0.0 $'
+# -mod=vendor should cause 'go list' flags that look up versions to fail.
+! go list -mod=vendor -versions -m x
+stderr '^go list -m: can''t determine available versions using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$'
+! go list -mod=vendor -u -m x
+stderr '^go list -m: can''t determine available upgrades using the vendor directory\n\t\(Use -mod=mod or -mod=readonly to bypass.\)$'
+
# 'go list -mod=vendor -m' on a transitive dependency that does not
# provide vendored packages should give a helpful error rather than
# 'not a known dependency'.
diff --git a/libgo/go/cmd/go/testdata/script/modfile_flag.txt b/libgo/go/cmd/go/testdata/script/modfile_flag.txt
index 1409be9..f05bf03 100644
--- a/libgo/go/cmd/go/testdata/script/modfile_flag.txt
+++ b/libgo/go/cmd/go/testdata/script/modfile_flag.txt
@@ -11,6 +11,15 @@ cp go.sum go.sum.orig
go mod init example.com/m
grep example.com/m go.alt.mod
+# 'go env GOMOD' should print the path to the real file.
+# 'go env' does not recognize the '-modfile' flag.
+go env GOMOD
+stdout '^\$WORK[/\\]gopath[/\\]src[/\\]go.mod$'
+
+# 'go list -m' should print the effective go.mod file as GoMod though.
+go list -m -f '{{.GoMod}}'
+stdout '^go.alt.mod$'
+
# go mod edit should operate on the alternate file
go mod edit -require rsc.io/quote@v1.5.2
grep rsc.io/quote go.alt.mod
diff --git a/libgo/go/cmd/go/testdata/script/test_badtest.txt b/libgo/go/cmd/go/testdata/script/test_badtest.txt
index f5db694..75b3b68 100644
--- a/libgo/go/cmd/go/testdata/script/test_badtest.txt
+++ b/libgo/go/cmd/go/testdata/script/test_badtest.txt
@@ -1,11 +1,21 @@
env GO111MODULE=off
-! go test badtest/...
+! go test badtest/badexec
! stdout ^ok
stdout ^FAIL\tbadtest/badexec
+
+! go test badtest/badsyntax
+! stdout ^ok
stdout ^FAIL\tbadtest/badsyntax
+
+! go test badtest/badvar
+! stdout ^ok
stdout ^FAIL\tbadtest/badvar
+! go test notest
+! stdout ^ok
+stderr '^notest.hello.go:6:1: .*declaration' # Exercise issue #7108
+
-- badtest/badexec/x_test.go --
package badexec
@@ -30,3 +40,10 @@ package badvar_test
func f() {
_ = notdefined
}
+-- notest/hello.go --
+package notest
+
+func hello() {
+ println("hello world")
+}
+Hello world
diff --git a/libgo/go/cmd/go/testdata/src/badc/x.c b/libgo/go/cmd/go/testdata/src/badc/x.c
deleted file mode 100644
index f6cbf69..0000000
--- a/libgo/go/cmd/go/testdata/src/badc/x.c
+++ /dev/null
@@ -1 +0,0 @@
-// C code!
diff --git a/libgo/go/cmd/go/testdata/src/badc/x.go b/libgo/go/cmd/go/testdata/src/badc/x.go
deleted file mode 100644
index bfa1de2..0000000
--- a/libgo/go/cmd/go/testdata/src/badc/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package badc
diff --git a/libgo/go/cmd/go/testdata/src/badpkg/x.go b/libgo/go/cmd/go/testdata/src/badpkg/x.go
deleted file mode 100644
index dda35e8..0000000
--- a/libgo/go/cmd/go/testdata/src/badpkg/x.go
+++ /dev/null
@@ -1 +0,0 @@
-pkg badpkg
diff --git a/libgo/go/cmd/go/testdata/src/bench/x_test.go b/libgo/go/cmd/go/testdata/src/bench/x_test.go
deleted file mode 100644
index 32cabf8..0000000
--- a/libgo/go/cmd/go/testdata/src/bench/x_test.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package bench
-
-import "testing"
-
-func Benchmark(b *testing.B) {
-}
diff --git a/libgo/go/cmd/go/testdata/src/benchfatal/x_test.go b/libgo/go/cmd/go/testdata/src/benchfatal/x_test.go
deleted file mode 100644
index 8d3a5de..0000000
--- a/libgo/go/cmd/go/testdata/src/benchfatal/x_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package benchfatal
-
-import "testing"
-
-func BenchmarkThatCallsFatal(b *testing.B) {
- b.Fatal("called by benchmark")
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgoasm/p.go b/libgo/go/cmd/go/testdata/src/cgoasm/p.go
deleted file mode 100644
index 148b47f..0000000
--- a/libgo/go/cmd/go/testdata/src/cgoasm/p.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package p
-
-/*
-// hi
-*/
-import "C"
-
-func F() {}
diff --git a/libgo/go/cmd/go/testdata/src/cgoasm/p.s b/libgo/go/cmd/go/testdata/src/cgoasm/p.s
deleted file mode 100644
index aaade03..0000000
--- a/libgo/go/cmd/go/testdata/src/cgoasm/p.s
+++ /dev/null
@@ -1,2 +0,0 @@
-TEXT asm(SB),$0
- RET
diff --git a/libgo/go/cmd/go/testdata/src/cgocover/p.go b/libgo/go/cmd/go/testdata/src/cgocover/p.go
deleted file mode 100644
index a6a3891..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover/p.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package p
-
-/*
-void
-f(void)
-{
-}
-*/
-import "C"
-
-var b bool
-
-func F() {
- if b {
- for {
- }
- }
- C.f()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover/p_test.go b/libgo/go/cmd/go/testdata/src/cgocover/p_test.go
deleted file mode 100644
index a8f057e..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover/p_test.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p
-
-import "testing"
-
-func TestF(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover2/p.go b/libgo/go/cmd/go/testdata/src/cgocover2/p.go
deleted file mode 100644
index a6a3891..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover2/p.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package p
-
-/*
-void
-f(void)
-{
-}
-*/
-import "C"
-
-var b bool
-
-func F() {
- if b {
- for {
- }
- }
- C.f()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover2/x_test.go b/libgo/go/cmd/go/testdata/src/cgocover2/x_test.go
deleted file mode 100644
index f4790d2..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover2/x_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p_test
-
-import (
- . "cgocover2"
- "testing"
-)
-
-func TestF(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover3/p.go b/libgo/go/cmd/go/testdata/src/cgocover3/p.go
deleted file mode 100644
index a6a3891..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover3/p.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package p
-
-/*
-void
-f(void)
-{
-}
-*/
-import "C"
-
-var b bool
-
-func F() {
- if b {
- for {
- }
- }
- C.f()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover3/p_test.go b/libgo/go/cmd/go/testdata/src/cgocover3/p_test.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover3/p_test.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/cgocover3/x_test.go b/libgo/go/cmd/go/testdata/src/cgocover3/x_test.go
deleted file mode 100644
index 97d0e0f..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover3/x_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p_test
-
-import (
- . "cgocover3"
- "testing"
-)
-
-func TestF(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go b/libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover4/notcgo.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/cgocover4/p.go b/libgo/go/cmd/go/testdata/src/cgocover4/p.go
deleted file mode 100644
index a6a3891..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover4/p.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package p
-
-/*
-void
-f(void)
-{
-}
-*/
-import "C"
-
-var b bool
-
-func F() {
- if b {
- for {
- }
- }
- C.f()
-}
diff --git a/libgo/go/cmd/go/testdata/src/cgocover4/x_test.go b/libgo/go/cmd/go/testdata/src/cgocover4/x_test.go
deleted file mode 100644
index fd9bae7..0000000
--- a/libgo/go/cmd/go/testdata/src/cgocover4/x_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p_test
-
-import (
- . "cgocover4"
- "testing"
-)
-
-func TestF(t *testing.T) {
- F()
-}
diff --git a/libgo/go/cmd/go/testdata/src/dupload/dupload.go b/libgo/go/cmd/go/testdata/src/dupload/dupload.go
deleted file mode 100644
index 2f07852..0000000
--- a/libgo/go/cmd/go/testdata/src/dupload/dupload.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package main
-
-import (
- _ "dupload/p2"
- _ "p"
-)
-
-func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/dupload/p/p.go b/libgo/go/cmd/go/testdata/src/dupload/p/p.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/dupload/p/p.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/dupload/p2/p2.go b/libgo/go/cmd/go/testdata/src/dupload/p2/p2.go
deleted file mode 100644
index 8a80979..0000000
--- a/libgo/go/cmd/go/testdata/src/dupload/p2/p2.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p2
-
-import _ "dupload/vendor/p"
diff --git a/libgo/go/cmd/go/testdata/src/dupload/vendor/p/p.go b/libgo/go/cmd/go/testdata/src/dupload/vendor/p/p.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/dupload/vendor/p/p.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/gencycle/gencycle.go b/libgo/go/cmd/go/testdata/src/gencycle/gencycle.go
deleted file mode 100644
index 600afd9..0000000
--- a/libgo/go/cmd/go/testdata/src/gencycle/gencycle.go
+++ /dev/null
@@ -1,5 +0,0 @@
-//go:generate echo hello world
-
-package gencycle
-
-import _ "gencycle"
diff --git a/libgo/go/cmd/go/testdata/src/importmain/ismain/main.go b/libgo/go/cmd/go/testdata/src/importmain/ismain/main.go
deleted file mode 100644
index bf01907..0000000
--- a/libgo/go/cmd/go/testdata/src/importmain/ismain/main.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package main
-
-import _ "importmain/test"
-
-func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/importmain/test/test.go b/libgo/go/cmd/go/testdata/src/importmain/test/test.go
deleted file mode 100644
index 56e5404..0000000
--- a/libgo/go/cmd/go/testdata/src/importmain/test/test.go
+++ /dev/null
@@ -1 +0,0 @@
-package test
diff --git a/libgo/go/cmd/go/testdata/src/importmain/test/test_test.go b/libgo/go/cmd/go/testdata/src/importmain/test/test_test.go
deleted file mode 100644
index 2268a82..0000000
--- a/libgo/go/cmd/go/testdata/src/importmain/test/test_test.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package test_test
-
-import "testing"
-import _ "importmain/ismain"
-
-func TestCase(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/src/multimain/multimain_test.go b/libgo/go/cmd/go/testdata/src/multimain/multimain_test.go
deleted file mode 100644
index 007a86a..0000000
--- a/libgo/go/cmd/go/testdata/src/multimain/multimain_test.go
+++ /dev/null
@@ -1,16 +0,0 @@
-package multimain_test
-
-import "testing"
-
-func TestMain(m *testing.M) {
- // Some users run m.Run multiple times, changing
- // some kind of global state between runs.
- // This used to work so I guess now it has to keep working.
- // See golang.org/issue/23129.
- m.Run()
- m.Run()
-}
-
-func Test(t *testing.T) {
- t.Log("notwithstanding")
-}
diff --git a/libgo/go/cmd/go/testdata/src/not_main/not_main.go b/libgo/go/cmd/go/testdata/src/not_main/not_main.go
deleted file mode 100644
index 75a397c..0000000
--- a/libgo/go/cmd/go/testdata/src/not_main/not_main.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package not_main
-
-func F() {}
diff --git a/libgo/go/cmd/go/testdata/src/notest/hello.go b/libgo/go/cmd/go/testdata/src/notest/hello.go
deleted file mode 100644
index 7c42c32..0000000
--- a/libgo/go/cmd/go/testdata/src/notest/hello.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package notest
-
-func hello() {
- println("hello world")
-}
-Hello world
diff --git a/libgo/go/cmd/go/testdata/src/run/bad.go b/libgo/go/cmd/go/testdata/src/run/bad.go
deleted file mode 100644
index c1cc3ac..0000000
--- a/libgo/go/cmd/go/testdata/src/run/bad.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package main
-
-import _ "run/subdir/internal/private"
-
-func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/run/good.go b/libgo/go/cmd/go/testdata/src/run/good.go
deleted file mode 100644
index 0b67dce..0000000
--- a/libgo/go/cmd/go/testdata/src/run/good.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package main
-
-import _ "run/internal"
-
-func main() {}
diff --git a/libgo/go/cmd/go/testdata/src/run/internal/internal.go b/libgo/go/cmd/go/testdata/src/run/internal/internal.go
deleted file mode 100644
index 5bf0569..0000000
--- a/libgo/go/cmd/go/testdata/src/run/internal/internal.go
+++ /dev/null
@@ -1 +0,0 @@
-package internal
diff --git a/libgo/go/cmd/go/testdata/src/run/subdir/internal/private/private.go b/libgo/go/cmd/go/testdata/src/run/subdir/internal/private/private.go
deleted file mode 100644
index 735e4dc..0000000
--- a/libgo/go/cmd/go/testdata/src/run/subdir/internal/private/private.go
+++ /dev/null
@@ -1 +0,0 @@
-package private
diff --git a/libgo/go/cmd/go/testdata/src/sleepy1/p_test.go b/libgo/go/cmd/go/testdata/src/sleepy1/p_test.go
deleted file mode 100644
index 333be7d..0000000
--- a/libgo/go/cmd/go/testdata/src/sleepy1/p_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p
-
-import (
- "testing"
- "time"
-)
-
-func Test1(t *testing.T) {
- time.Sleep(200 * time.Millisecond)
-}
diff --git a/libgo/go/cmd/go/testdata/src/sleepy2/p_test.go b/libgo/go/cmd/go/testdata/src/sleepy2/p_test.go
deleted file mode 100644
index 333be7d..0000000
--- a/libgo/go/cmd/go/testdata/src/sleepy2/p_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p
-
-import (
- "testing"
- "time"
-)
-
-func Test1(t *testing.T) {
- time.Sleep(200 * time.Millisecond)
-}
diff --git a/libgo/go/cmd/go/testdata/src/sleepybad/p.go b/libgo/go/cmd/go/testdata/src/sleepybad/p.go
deleted file mode 100644
index e05b403..0000000
--- a/libgo/go/cmd/go/testdata/src/sleepybad/p.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package p
-
-// missing import
-
-var _ = io.DoesNotExist
diff --git a/libgo/go/cmd/go/testdata/src/syntaxerror/x.go b/libgo/go/cmd/go/testdata/src/syntaxerror/x.go
deleted file mode 100644
index c89cd18..0000000
--- a/libgo/go/cmd/go/testdata/src/syntaxerror/x.go
+++ /dev/null
@@ -1 +0,0 @@
-package p
diff --git a/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go b/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go
deleted file mode 100644
index 2460743..0000000
--- a/libgo/go/cmd/go/testdata/src/syntaxerror/x_test.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package p
-
-func f() (x.y, z int) {
-}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go
deleted file mode 100644
index 65ab76d..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p1
-
-import _ "testcycle/p2"
-
-func init() {
- println("p1 init")
-}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go b/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go
deleted file mode 100644
index 75abb13..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/p1/p1_test.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package p1
-
-import "testing"
-
-func Test(t *testing.T) {
-}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go b/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go
deleted file mode 100644
index 7e26cdf..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/p2/p2.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package p2
-
-import _ "testcycle/p3"
-
-func init() {
- println("p2 init")
-}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go
deleted file mode 100644
index bb0a2f4..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package p3
-
-func init() {
- println("p3 init")
-}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go b/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go
deleted file mode 100644
index 9b4b075..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/p3/p3_test.go
+++ /dev/null
@@ -1,10 +0,0 @@
-package p3
-
-import (
- "testing"
-
- _ "testcycle/p1"
-)
-
-func Test(t *testing.T) {
-}
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/q1/q1.go b/libgo/go/cmd/go/testdata/src/testcycle/q1/q1.go
deleted file mode 100644
index 7a471f0..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/q1/q1.go
+++ /dev/null
@@ -1 +0,0 @@
-package q1
diff --git a/libgo/go/cmd/go/testdata/src/testcycle/q1/q1_test.go b/libgo/go/cmd/go/testdata/src/testcycle/q1/q1_test.go
deleted file mode 100644
index ca81bd2..0000000
--- a/libgo/go/cmd/go/testdata/src/testcycle/q1/q1_test.go
+++ /dev/null
@@ -1,6 +0,0 @@
-package q1
-
-import "testing"
-import _ "testcycle/q1"
-
-func Test(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/src/testdep/p1/p1.go b/libgo/go/cmd/go/testdata/src/testdep/p1/p1.go
deleted file mode 100644
index a457035..0000000
--- a/libgo/go/cmd/go/testdata/src/testdep/p1/p1.go
+++ /dev/null
@@ -1 +0,0 @@
-package p1
diff --git a/libgo/go/cmd/go/testdata/src/testdep/p1/p1_test.go b/libgo/go/cmd/go/testdata/src/testdep/p1/p1_test.go
deleted file mode 100644
index 8be7533..0000000
--- a/libgo/go/cmd/go/testdata/src/testdep/p1/p1_test.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p1
-
-import _ "testdep/p2"
diff --git a/libgo/go/cmd/go/testdata/src/testdep/p2/p2.go b/libgo/go/cmd/go/testdata/src/testdep/p2/p2.go
deleted file mode 100644
index 15ba2ea..0000000
--- a/libgo/go/cmd/go/testdata/src/testdep/p2/p2.go
+++ /dev/null
@@ -1,3 +0,0 @@
-package p2
-
-import _ "testdep/p3"
diff --git a/libgo/go/cmd/go/testdata/src/testdep/p3/p3.go b/libgo/go/cmd/go/testdata/src/testdep/p3/p3.go
deleted file mode 100644
index 0219e7f..0000000
--- a/libgo/go/cmd/go/testdata/src/testdep/p3/p3.go
+++ /dev/null
@@ -1,3 +0,0 @@
-// +build ignore
-
-package ignored
diff --git a/libgo/go/cmd/go/testdata/src/testnorun/p.go b/libgo/go/cmd/go/testdata/src/testnorun/p.go
deleted file mode 100644
index 71a9a56..0000000
--- a/libgo/go/cmd/go/testdata/src/testnorun/p.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package p
-
-func init() {
- panic("go test must not link and run test binaries without tests")
-}
diff --git a/libgo/go/cmd/go/testdata/src/testrace/race_test.go b/libgo/go/cmd/go/testdata/src/testrace/race_test.go
deleted file mode 100644
index 7ec0c6d..0000000
--- a/libgo/go/cmd/go/testdata/src/testrace/race_test.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package testrace
-
-import "testing"
-
-func TestRace(t *testing.T) {
- for i := 0; i < 10; i++ {
- c := make(chan int)
- x := 1
- go func() {
- x = 2
- c <- 1
- }()
- x = 3
- <-c
- _ = x
- }
-}
-
-func BenchmarkRace(b *testing.B) {
- for i := 0; i < b.N; i++ {
- c := make(chan int)
- x := 1
- go func() {
- x = 2
- c <- 1
- }()
- x = 3
- <-c
- _ = x
- }
-}
diff --git a/libgo/go/cmd/go/testdata/src/testregexp/x_test.go b/libgo/go/cmd/go/testdata/src/testregexp/x_test.go
deleted file mode 100644
index 7573e79..0000000
--- a/libgo/go/cmd/go/testdata/src/testregexp/x_test.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package x
-
-import "testing"
-
-func TestX(t *testing.T) {
- t.Logf("LOG: X running")
- t.Run("Y", func(t *testing.T) {
- t.Logf("LOG: Y running")
- })
-}
-
-func BenchmarkX(b *testing.B) {
- b.Logf("LOG: X running N=%d", b.N)
- b.Run("Y", func(b *testing.B) {
- b.Logf("LOG: Y running N=%d", b.N)
- })
-}
diff --git a/libgo/go/cmd/go/testdata/src/testregexp/z_test.go b/libgo/go/cmd/go/testdata/src/testregexp/z_test.go
deleted file mode 100644
index 4fd1979..0000000
--- a/libgo/go/cmd/go/testdata/src/testregexp/z_test.go
+++ /dev/null
@@ -1,19 +0,0 @@
-package x
-
-import "testing"
-
-func TestZ(t *testing.T) {
- t.Logf("LOG: Z running")
-}
-
-func TestXX(t *testing.T) {
- t.Logf("LOG: XX running")
-}
-
-func BenchmarkZ(b *testing.B) {
- b.Logf("LOG: Z running N=%d", b.N)
-}
-
-func BenchmarkXX(b *testing.B) {
- b.Logf("LOG: XX running N=%d", b.N)
-}
diff --git a/libgo/go/crypto/tls/tls.go b/libgo/go/crypto/tls/tls.go
index 228f4a7..af44485 100644
--- a/libgo/go/crypto/tls/tls.go
+++ b/libgo/go/crypto/tls/tls.go
@@ -116,9 +116,10 @@ func DialWithDialer(dialer *net.Dialer, network, addr string, config *Config) (*
if timeout != 0 {
errChannel = make(chan error, 2)
- time.AfterFunc(timeout, func() {
+ timer := time.AfterFunc(timeout, func() {
errChannel <- timeoutError{}
})
+ defer timer.Stop()
}
rawConn, err := dialer.Dial(network, addr)
diff --git a/libgo/go/crypto/x509/root_cgo_darwin.go b/libgo/go/crypto/x509/root_cgo_darwin.go
index 255a8d3..8a54282 100644
--- a/libgo/go/crypto/x509/root_cgo_darwin.go
+++ b/libgo/go/crypto/x509/root_cgo_darwin.go
@@ -159,7 +159,7 @@ static Boolean isRootCertificate(SecCertificateRef cert, CFErrorRef *errRef) {
//
// Note: The CFDataRef returned in pemRoots and untrustedPemRoots must
// be released (using CFRelease) after we've consumed its content.
-int CopyPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugDarwinRoots) {
+static int CopyPEMRoots(CFDataRef *pemRoots, CFDataRef *untrustedPemRoots, bool debugDarwinRoots) {
int i;
if (debugDarwinRoots) {
diff --git a/libgo/go/crypto/x509/root_windows.go b/libgo/go/crypto/x509/root_windows.go
index 54ab1dc..34d5853 100644
--- a/libgo/go/crypto/x509/root_windows.go
+++ b/libgo/go/crypto/x509/root_windows.go
@@ -219,10 +219,26 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
if err != nil {
return nil, err
}
+ if len(chain) < 1 {
+ return nil, errors.New("x509: internal error: system verifier returned an empty chain")
+ }
- chains = append(chains, chain)
+ // Mitigate CVE-2020-0601, where the Windows system verifier might be
+ // tricked into using custom curve parameters for a trusted root, by
+ // double-checking all ECDSA signatures. If the system was tricked into
+ // using spoofed parameters, the signature will be invalid for the correct
+ // ones we parsed. (We don't support custom curves ourselves.)
+ for i, parent := range chain[1:] {
+ if parent.PublicKeyAlgorithm != ECDSA {
+ continue
+ }
+ if err := parent.CheckSignature(chain[i].SignatureAlgorithm,
+ chain[i].RawTBSCertificate, chain[i].Signature); err != nil {
+ return nil, err
+ }
+ }
- return chains, nil
+ return [][]*Certificate{chain}, nil
}
func loadSystemRoots() (*CertPool, error) {
diff --git a/libgo/go/database/sql/sql_test.go b/libgo/go/database/sql/sql_test.go
index ed0099e..6f59260 100644
--- a/libgo/go/database/sql/sql_test.go
+++ b/libgo/go/database/sql/sql_test.go
@@ -629,7 +629,8 @@ func TestPoolExhaustOnCancel(t *testing.T) {
go func() {
rows, err := db.Query("SELECT|people|name,photo|")
if err != nil {
- t.Fatalf("Query: %v", err)
+ t.Errorf("Query: %v", err)
+ return
}
rows.Close()
saturateDone.Done()
@@ -637,6 +638,9 @@ func TestPoolExhaustOnCancel(t *testing.T) {
}
saturate.Wait()
+ if t.Failed() {
+ t.FailNow()
+ }
state = 2
// Now cancel the request while it is waiting.
diff --git a/libgo/go/go/build/build_test.go b/libgo/go/go/build/build_test.go
index 086a42e..4d11223 100644
--- a/libgo/go/go/build/build_test.go
+++ b/libgo/go/go/build/build_test.go
@@ -342,20 +342,38 @@ func TestImportDirNotExist(t *testing.T) {
{"Import(full, FindOnly)", "go/build/doesnotexist", "", FindOnly},
{"Import(local, FindOnly)", "./doesnotexist", filepath.Join(ctxt.GOROOT, "src/go/build"), FindOnly},
}
- for _, test := range tests {
- p, err := ctxt.Import(test.path, test.srcDir, test.mode)
- if err == nil || !strings.HasPrefix(err.Error(), "cannot find package") {
- t.Errorf(`%s got error: %q, want "cannot find package" error`, test.label, err)
- }
- // If an error occurs, build.Import is documented to return
- // a non-nil *Package containing partial information.
- if p == nil {
- t.Fatalf(`%s got nil p, want non-nil *Package`, test.label)
- }
- // Verify partial information in p.
- if p.ImportPath != "go/build/doesnotexist" {
- t.Errorf(`%s got p.ImportPath: %q, want "go/build/doesnotexist"`, test.label, p.ImportPath)
- }
+
+ defer os.Setenv("GO111MODULE", os.Getenv("GO111MODULE"))
+
+ for _, GO111MODULE := range []string{"off", "on"} {
+ t.Run("GO111MODULE="+GO111MODULE, func(t *testing.T) {
+ os.Setenv("GO111MODULE", GO111MODULE)
+
+ for _, test := range tests {
+ p, err := ctxt.Import(test.path, test.srcDir, test.mode)
+
+ errOk := (err != nil && strings.HasPrefix(err.Error(), "cannot find package"))
+ wantErr := `"cannot find package" error`
+ if test.srcDir == "" {
+ if err != nil && strings.Contains(err.Error(), "is not in GOROOT") {
+ errOk = true
+ }
+ wantErr = `"cannot find package" or "is not in GOROOT" error`
+ }
+ if !errOk {
+ t.Errorf("%s got error: %q, want %s", test.label, err, wantErr)
+ }
+ // If an error occurs, build.Import is documented to return
+ // a non-nil *Package containing partial information.
+ if p == nil {
+ t.Fatalf(`%s got nil p, want non-nil *Package`, test.label)
+ }
+ // Verify partial information in p.
+ if p.ImportPath != "go/build/doesnotexist" {
+ t.Errorf(`%s got p.ImportPath: %q, want "go/build/doesnotexist"`, test.label, p.ImportPath)
+ }
+ }
+ })
}
}
diff --git a/libgo/go/go/build/deps_test.go b/libgo/go/go/build/deps_test.go
index fd256ee..a64c2b3 100644
--- a/libgo/go/go/build/deps_test.go
+++ b/libgo/go/go/build/deps_test.go
@@ -168,7 +168,7 @@ var pkgDeps = map[string][]string{
},
"internal/cfg": {"L0"},
- "internal/poll": {"L0", "internal/oserror", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows"},
+ "internal/poll": {"L0", "internal/oserror", "internal/race", "syscall", "time", "unicode/utf16", "unicode/utf8", "internal/syscall/windows", "internal/syscall/unix"},
"internal/testlog": {"L0"},
"os": {"L1", "os", "syscall", "time", "internal/oserror", "internal/poll", "internal/syscall/windows", "internal/syscall/unix", "internal/testlog"},
"path/filepath": {"L2", "os", "syscall", "internal/syscall/windows"},
diff --git a/libgo/go/go/doc/example.go b/libgo/go/go/doc/example.go
index 868db8a..a010d3a 100644
--- a/libgo/go/go/doc/example.go
+++ b/libgo/go/go/doc/example.go
@@ -62,7 +62,7 @@ func Examples(testFiles ...*ast.File) []*Example {
if !ok || f.Recv != nil {
continue
}
- if params := f.Type.Params; params.List != nil {
+ if params := f.Type.Params; len(params.List) != 0 {
continue // function has params; not a valid example
}
numDecl++
diff --git a/libgo/go/go/types/builtins.go b/libgo/go/go/types/builtins.go
index af374b7..3756303 100644
--- a/libgo/go/go/types/builtins.go
+++ b/libgo/go/go/types/builtins.go
@@ -559,7 +559,7 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
base := derefStructPtr(x.typ)
sel := selx.Sel.Name
- obj, index, indirect := check.LookupFieldOrMethod(base, false, check.pkg, sel)
+ obj, index, indirect := check.lookupFieldOrMethod(base, false, check.pkg, sel)
switch obj.(type) {
case nil:
check.invalidArg(x.pos(), "%s has no single field %s", base, sel)
diff --git a/libgo/go/go/types/call.go b/libgo/go/go/types/call.go
index 31f9372..689ef87 100644
--- a/libgo/go/go/types/call.go
+++ b/libgo/go/go/types/call.go
@@ -370,7 +370,7 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) {
goto Error
}
- obj, index, indirect = check.LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
+ obj, index, indirect = check.lookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
switch {
case index != nil:
diff --git a/libgo/go/go/types/lookup.go b/libgo/go/go/types/lookup.go
index 648e100..342c8ba 100644
--- a/libgo/go/go/types/lookup.go
+++ b/libgo/go/go/types/lookup.go
@@ -33,19 +33,19 @@ package types
// the method's formal receiver base type, nor was the receiver addressable.
//
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
- return (*Checker)(nil).LookupFieldOrMethod(T, addressable, pkg, name)
+ return (*Checker)(nil).lookupFieldOrMethod(T, addressable, pkg, name)
}
-// Internal use of Checker.LookupFieldOrMethod: If the obj result is a method
+// Internal use of Checker.lookupFieldOrMethod: If the obj result is a method
// associated with a concrete (non-interface) type, the method's signature
// may not be fully set up. Call Checker.objDecl(obj, nil) before accessing
// the method's type.
// TODO(gri) Now that we provide the *Checker, we can probably remove this
-// caveat by calling Checker.objDecl from LookupFieldOrMethod. Investigate.
+// caveat by calling Checker.objDecl from lookupFieldOrMethod. Investigate.
-// LookupFieldOrMethod is like the external version but completes interfaces
+// lookupFieldOrMethod is like the external version but completes interfaces
// as necessary.
-func (check *Checker) LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
// Methods cannot be associated to a named pointer type
// (spec: "The type denoted by T is called the receiver base type;
// it must not be a pointer or interface type and it must be declared
@@ -55,7 +55,7 @@ func (check *Checker) LookupFieldOrMethod(T Type, addressable bool, pkg *Package
// not have found it for T (see also issue 8590).
if t, _ := T.(*Named); t != nil {
if p, _ := t.underlying.(*Pointer); p != nil {
- obj, index, indirect = check.lookupFieldOrMethod(p, false, pkg, name)
+ obj, index, indirect = check.rawLookupFieldOrMethod(p, false, pkg, name)
if _, ok := obj.(*Func); ok {
return nil, nil, false
}
@@ -63,7 +63,7 @@ func (check *Checker) LookupFieldOrMethod(T Type, addressable bool, pkg *Package
}
}
- return check.lookupFieldOrMethod(T, addressable, pkg, name)
+ return check.rawLookupFieldOrMethod(T, addressable, pkg, name)
}
// TODO(gri) The named type consolidation and seen maps below must be
@@ -71,8 +71,8 @@ func (check *Checker) LookupFieldOrMethod(T Type, addressable bool, pkg *Package
// types always have only one representation (even when imported
// indirectly via different packages.)
-// lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
-func (check *Checker) lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
+// rawLookupFieldOrMethod should only be called by lookupFieldOrMethod and missingMethod.
+func (check *Checker) rawLookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
// WARNING: The code in this function is extremely subtle - do not modify casually!
// This function and NewMethodSet should be kept in sync.
@@ -297,7 +297,7 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method *
// A concrete type implements T if it implements all methods of T.
for _, m := range T.allMethods {
- obj, _, _ := check.lookupFieldOrMethod(V, false, m.pkg, m.name)
+ obj, _, _ := check.rawLookupFieldOrMethod(V, false, m.pkg, m.name)
// we must have a method (not a field of matching function type)
f, _ := obj.(*Func)
diff --git a/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go b/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
index 528b9bf..f930f7e 100644
--- a/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
+++ b/libgo/go/golang.org/x/crypto/cryptobyte/asn1.go
@@ -470,7 +470,8 @@ func (s *String) ReadASN1GeneralizedTime(out *time.Time) bool {
// It reports whether the read was successful.
func (s *String) ReadASN1BitString(out *encoding_asn1.BitString) bool {
var bytes String
- if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 {
+ if !s.ReadASN1(&bytes, asn1.BIT_STRING) || len(bytes) == 0 ||
+ len(bytes)*8/8 != len(bytes) {
return false
}
@@ -740,7 +741,7 @@ func (s *String) readASN1(out *String, outTag *asn1.Tag, skipHeader bool) bool {
length = headerLen + len32
}
- if uint32(int(length)) != length || !s.ReadBytes((*[]byte)(out), int(length)) {
+ if int(length) < 0 || !s.ReadBytes((*[]byte)(out), int(length)) {
return false
}
if skipHeader && !out.Skip(int(headerLen)) {
diff --git a/libgo/go/golang.org/x/crypto/cryptobyte/string.go b/libgo/go/golang.org/x/crypto/cryptobyte/string.go
index 39bf98a..589d297 100644
--- a/libgo/go/golang.org/x/crypto/cryptobyte/string.go
+++ b/libgo/go/golang.org/x/crypto/cryptobyte/string.go
@@ -24,7 +24,7 @@ type String []byte
// read advances a String by n bytes and returns them. If less than n bytes
// remain, it returns nil.
func (s *String) read(n int) []byte {
- if len(*s) < n {
+ if len(*s) < n || n < 0 {
return nil
}
v := (*s)[:n]
@@ -105,11 +105,6 @@ func (s *String) readLengthPrefixed(lenLen int, outChild *String) bool {
length = length << 8
length = length | uint32(b)
}
- if int(length) < 0 {
- // This currently cannot overflow because we read uint24 at most, but check
- // anyway in case that changes in the future.
- return false
- }
v := s.read(int(length))
if v == nil {
return false
diff --git a/libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go b/libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go
index 1682eda45..32a9cef 100644
--- a/libgo/go/golang.org/x/crypto/poly1305/sum_noasm.go
+++ b/libgo/go/golang.org/x/crypto/poly1305/sum_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.
-// +build s390x,!go1.11 !arm,!amd64,!s390x,!ppc64le gccgo appengine nacl
+// +build s390x,!go1.11 !amd64,!s390x,!ppc64le gccgo appengine nacl
package poly1305
diff --git a/libgo/go/golang.org/x/mod/sumdb/note/note.go b/libgo/go/golang.org/x/mod/sumdb/note/note.go
index 3c8e67b..467d25e 100644
--- a/libgo/go/golang.org/x/mod/sumdb/note/note.go
+++ b/libgo/go/golang.org/x/mod/sumdb/note/note.go
@@ -4,9 +4,6 @@
// Package note defines the notes signed by the Go module database server.
//
-// This package is part of a DRAFT of what the Go module database server will look like.
-// Do not assume the details here are final!
-//
// A note is text signed by one or more server keys.
// The text should be ignored unless the note is signed by
// a trusted server key and the signature has been verified
diff --git a/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go b/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go
new file mode 100644
index 0000000..18c8a48
--- /dev/null
+++ b/libgo/go/golang.org/x/sys/cpu/cpu_riscv64.go
@@ -0,0 +1,7 @@
+// Copyright 2019 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.
+
+// +build riscv64
+
+package cpu
diff --git a/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
index 5c93a4f..e6bfe71 100644
--- a/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
+++ b/libgo/go/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go
@@ -87,6 +87,7 @@ var (
asmArchMips64LE = asmArch{name: "mips64le", bigEndian: false, stack: "R29", lr: true}
asmArchPpc64 = asmArch{name: "ppc64", bigEndian: true, stack: "R1", lr: true}
asmArchPpc64LE = asmArch{name: "ppc64le", bigEndian: false, stack: "R1", lr: true}
+ asmArchRISCV64 = asmArch{name: "riscv64", bigEndian: false, stack: "SP", lr: true}
asmArchS390X = asmArch{name: "s390x", bigEndian: true, stack: "R15", lr: true}
asmArchWasm = asmArch{name: "wasm", bigEndian: false, stack: "SP", lr: false}
@@ -101,6 +102,7 @@ var (
&asmArchMips64LE,
&asmArchPpc64,
&asmArchPpc64LE,
+ &asmArchRISCV64,
&asmArchS390X,
&asmArchWasm,
}
diff --git a/libgo/go/html/escape.go b/libgo/go/html/escape.go
index dae404f..1dc1287 100644
--- a/libgo/go/html/escape.go
+++ b/libgo/go/html/escape.go
@@ -12,7 +12,7 @@ import (
// These replacements permit compatibility with old numeric entities that
// assumed Windows-1252 encoding.
-// http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#consume-a-character-reference
+// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
var replacementTable = [...]rune{
'\u20AC', // First entry is what 0x80 should be replaced with.
'\u0081',
diff --git a/libgo/go/internal/poll/fcntl_js.go b/libgo/go/internal/poll/fcntl_js.go
new file mode 100644
index 0000000..120fc11
--- /dev/null
+++ b/libgo/go/internal/poll/fcntl_js.go
@@ -0,0 +1,14 @@
+// Copyright 2019 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.
+
+// +build js,wasm
+
+package poll
+
+import "syscall"
+
+// fcntl not supported on js/wasm
+func fcntl(fd int, cmd int, arg int) (int, error) {
+ return 0, syscall.ENOSYS
+}
diff --git a/libgo/go/internal/poll/fcntl_libc.go b/libgo/go/internal/poll/fcntl_libc.go
new file mode 100644
index 0000000..ed00f76
--- /dev/null
+++ b/libgo/go/internal/poll/fcntl_libc.go
@@ -0,0 +1,26 @@
+// Copyright 2019 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.
+
+// +build aix darwin solaris
+
+package poll
+
+import (
+ "syscall"
+)
+
+// Use a helper function to call fcntl. This is defined in C in
+// libgo/runtime.
+//extern __go_fcntl_uintptr
+func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
+
+func fcntl(fd int, cmd int, arg int) (int, error) {
+ syscall.Entersyscall()
+ r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg))
+ syscall.Exitsyscall()
+ if e != 0 {
+ return int(r), syscall.Errno(e)
+ }
+ return int(r), nil
+}
diff --git a/libgo/go/internal/poll/fcntl_syscall.go b/libgo/go/internal/poll/fcntl_syscall.go
new file mode 100644
index 0000000..d232e51
--- /dev/null
+++ b/libgo/go/internal/poll/fcntl_syscall.go
@@ -0,0 +1,26 @@
+// Copyright 2019 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.
+
+// +build dragonfly freebsd linux netbsd openbsd
+
+package poll
+
+import (
+ "syscall"
+)
+
+// Use a helper function to call fcntl. This is defined in C in
+// libgo/runtime.
+//extern __go_fcntl_uintptr
+func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
+
+func fcntl(fd int, cmd int, arg int) (int, error) {
+ syscall.Entersyscall()
+ r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg))
+ syscall.Exitsyscall()
+ if e != 0 {
+ return int(r), syscall.Errno(e)
+ }
+ return int(r), nil
+}
diff --git a/libgo/go/internal/poll/fd_fsync_darwin.go b/libgo/go/internal/poll/fd_fsync_darwin.go
index 6cd3f91..9175149 100644
--- a/libgo/go/internal/poll/fd_fsync_darwin.go
+++ b/libgo/go/internal/poll/fd_fsync_darwin.go
@@ -4,10 +4,7 @@
package poll
-import (
- "syscall"
- _ "unsafe" // for go:linkname
-)
+import "syscall"
// Fsync invokes SYS_FCNTL with SYS_FULLFSYNC because
// on OS X, SYS_FSYNC doesn't fully flush contents to disk.
@@ -21,18 +18,3 @@ func (fd *FD) Fsync() error {
_, e1 := fcntl(fd.Sysfd, syscall.F_FULLFSYNC, 0)
return e1
}
-
-// Use a helper function to call fcntl. This is defined in C in
-// libgo/runtime.
-//extern __go_fcntl_uintptr
-func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
-
-func fcntl(fd int, cmd int, arg int) (int, error) {
- syscall.Entersyscall()
- r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg))
- syscall.Exitsyscall()
- if e != 0 {
- return int(r), syscall.Errno(e)
- }
- return int(r), nil
-}
diff --git a/libgo/go/internal/poll/fd_fsync_posix.go b/libgo/go/internal/poll/fd_fsync_posix.go
index 67b76f8..dfc8b77 100644
--- a/libgo/go/internal/poll/fd_fsync_posix.go
+++ b/libgo/go/internal/poll/fd_fsync_posix.go
@@ -8,11 +8,6 @@ package poll
import "syscall"
-// Use a helper function to call fcntl. This is defined in C in
-// libgo/runtime.
-//extern __go_fcntl_uintptr
-func libc_fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
-
// Fsync wraps syscall.Fsync.
func (fd *FD) Fsync() error {
if err := fd.incref(); err != nil {
@@ -21,13 +16,3 @@ func (fd *FD) Fsync() error {
defer fd.decref()
return syscall.Fsync(fd.Sysfd)
}
-
-func fcntl(fd int, cmd int, arg int) (int, error) {
- syscall.Entersyscall()
- r, e := libc_fcntl(uintptr(fd), uintptr(cmd), uintptr(arg))
- syscall.Exitsyscall()
- if e != 0 {
- return int(r), syscall.Errno(e)
- }
- return int(r), nil
-}
diff --git a/libgo/go/internal/poll/fd_unix.go b/libgo/go/internal/poll/fd_unix.go
index 6b8e476..213e815 100644
--- a/libgo/go/internal/poll/fd_unix.go
+++ b/libgo/go/internal/poll/fd_unix.go
@@ -451,7 +451,7 @@ var tryDupCloexec = int32(1)
// DupCloseOnExec dups fd and marks it close-on-exec.
func DupCloseOnExec(fd int) (int, string, error) {
- if atomic.LoadInt32(&tryDupCloexec) == 1 {
+ if syscall.F_DUPFD_CLOEXEC != 0 && atomic.LoadInt32(&tryDupCloexec) == 1 {
r0, e1 := fcntl(fd, syscall.F_DUPFD_CLOEXEC, 0)
if e1 == nil {
return r0, "", nil
diff --git a/libgo/go/internal/syscall/unix/nonblocking.go b/libgo/go/internal/syscall/unix/nonblocking.go
index cff5a53..9b39bb2 100644
--- a/libgo/go/internal/syscall/unix/nonblocking.go
+++ b/libgo/go/internal/syscall/unix/nonblocking.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.
-// +build aix dragonfly freebsd hurd linux netbsd openbsd solaris
+// +build dragonfly freebsd linux netbsd openbsd
package unix
diff --git a/libgo/go/internal/syscall/unix/nonblocking_darwin.go b/libgo/go/internal/syscall/unix/nonblocking_libc.go
index e3dd3a0..464314d 100644
--- a/libgo/go/internal/syscall/unix/nonblocking_darwin.go
+++ b/libgo/go/internal/syscall/unix/nonblocking_libc.go
@@ -2,23 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build darwin
+// +build aix darwin solaris
package unix
-import (
- "syscall"
- _ "unsafe" // for go:linkname
-)
+import "syscall"
+
+//extern __go_fcntl_uintptr
+func fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
func IsNonblock(fd int) (nonblocking bool, err error) {
- flag, e1 := fcntl(fd, syscall.F_GETFL, 0)
- if e1 != nil {
- return false, e1
+ flag, e1 := fcntl(uintptr(fd), syscall.F_GETFL, 0)
+ if e1 != 0 {
+ return false, syscall.Errno(e1)
}
return flag&syscall.O_NONBLOCK != 0, nil
}
-
-// Implemented in syscall/syscall_darwin.go.
-//go:linkname fcntl syscall.fcntl
-func fcntl(fd int, cmd int, arg int) (int, error)
diff --git a/libgo/go/io/example_test.go b/libgo/go/io/example_test.go
index edcd008..2eaab67 100644
--- a/libgo/go/io/example_test.go
+++ b/libgo/go/io/example_test.go
@@ -59,7 +59,7 @@ func ExampleCopyN() {
func ExampleReadAtLeast() {
r := strings.NewReader("some io.Reader stream to be read\n")
- buf := make([]byte, 33)
+ buf := make([]byte, 14)
if _, err := io.ReadAtLeast(r, buf, 4); err != nil {
log.Fatal(err)
}
@@ -78,10 +78,9 @@ func ExampleReadAtLeast() {
}
// Output:
- // some io.Reader stream to be read
- //
+ // some io.Reader
// error: short buffer
- // error: EOF
+ // error: unexpected EOF
}
func ExampleReadFull() {
diff --git a/libgo/go/math/big/arith_decl.go b/libgo/go/math/big/arith_decl.go
index 61df0df..0a139f1 100644
--- a/libgo/go/math/big/arith_decl.go
+++ b/libgo/go/math/big/arith_decl.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// +build ignore
-// +build !math_big_pure_go
+// +build !math_big_pure_go,!riscv64
package big
diff --git a/libgo/go/math/big/arith_decl_pure.go b/libgo/go/math/big/arith_decl_pure.go
index ee8f922..8853eb6 100644
--- a/libgo/go/math/big/arith_decl_pure.go
+++ b/libgo/go/math/big/arith_decl_pure.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.
-// -build math_big_pure_go
+// -build math_big_pure_go riscv64
package big
diff --git a/libgo/go/math/big/int.go b/libgo/go/math/big/int.go
index bf1fa73..bec0a81 100644
--- a/libgo/go/math/big/int.go
+++ b/libgo/go/math/big/int.go
@@ -504,9 +504,14 @@ func (z *Int) Exp(x, y, m *Int) *Int {
// GCD sets z to the greatest common divisor of a and b and returns z.
// If x or y are not nil, GCD sets their value such that z = a*x + b*y.
+//
+// a and b may be positive, zero or negative.
// Regardless of the signs of a and b, z is always >= 0.
+//
// If a == b == 0, GCD sets z = x = y = 0.
+//
// If a == 0 and b != 0, GCD sets z = |b|, x = 0, y = sign(b) * 1.
+//
// If a != 0 and b == 0, GCD sets z = |a|, x = sign(a) * 1, y = 0.
func (z *Int) GCD(x, y, a, b *Int) *Int {
if len(a.abs) == 0 || len(b.abs) == 0 {
diff --git a/libgo/go/net/dial_test.go b/libgo/go/net/dial_test.go
index ae40079..493cdfc 100644
--- a/libgo/go/net/dial_test.go
+++ b/libgo/go/net/dial_test.go
@@ -174,7 +174,7 @@ func dialClosedPort(t *testing.T) (actual, expected time.Duration) {
}
addr := l.Addr().String()
l.Close()
- // On OpenBSD, interference from TestSelfConnect is mysteriously
+ // On OpenBSD, interference from TestTCPSelfConnect is mysteriously
// causing the first attempt to hang for a few seconds, so we throw
// away the first result and keep the second.
for i := 1; ; i++ {
diff --git a/libgo/go/net/dnsclient_unix_test.go b/libgo/go/net/dnsclient_unix_test.go
index 6d72817..e8f81e8 100644
--- a/libgo/go/net/dnsclient_unix_test.go
+++ b/libgo/go/net/dnsclient_unix_test.go
@@ -173,7 +173,7 @@ func TestAvoidDNSName(t *testing.T) {
// Without stuff before onion/local, they're fine to
// use DNS. With a search path,
- // "onion.vegegtables.com" can use DNS. Without a
+ // "onion.vegetables.com" can use DNS. Without a
// search path (or with a trailing dot), the queries
// are just kinda useless, but don't reveal anything
// private.
diff --git a/libgo/go/net/http/cgi/matryoshka_test.go b/libgo/go/net/http/cgi/integration_test.go
index 32d59c0..32d59c0 100644
--- a/libgo/go/net/http/cgi/matryoshka_test.go
+++ b/libgo/go/net/http/cgi/integration_test.go
diff --git a/libgo/go/net/http/client.go b/libgo/go/net/http/client.go
index 6a8c59a..a496f1c 100644
--- a/libgo/go/net/http/client.go
+++ b/libgo/go/net/http/client.go
@@ -288,10 +288,17 @@ func timeBeforeContextDeadline(t time.Time, ctx context.Context) bool {
// knownRoundTripperImpl reports whether rt is a RoundTripper that's
// maintained by the Go team and known to implement the latest
-// optional semantics (notably contexts).
-func knownRoundTripperImpl(rt RoundTripper) bool {
- switch rt.(type) {
- case *Transport, *http2Transport:
+// optional semantics (notably contexts). The Request is used
+// to check whether this particular request is using an alternate protocol,
+// in which case we need to check the RoundTripper for that protocol.
+func knownRoundTripperImpl(rt RoundTripper, req *Request) bool {
+ switch t := rt.(type) {
+ case *Transport:
+ if altRT := t.alternateRoundTripper(req); altRT != nil {
+ return knownRoundTripperImpl(altRT, req)
+ }
+ return true
+ case *http2Transport, http2noDialH2RoundTripper:
return true
}
// There's a very minor chance of a false positive with this.
@@ -319,7 +326,7 @@ func setRequestCancel(req *Request, rt RoundTripper, deadline time.Time) (stopTi
if deadline.IsZero() {
return nop, alwaysFalse
}
- knownTransport := knownRoundTripperImpl(rt)
+ knownTransport := knownRoundTripperImpl(rt, req)
oldCtx := req.Context()
if req.Cancel == nil && knownTransport {
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index e8f7df2..4d6a085 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -24,6 +24,14 @@ import (
// ReverseProxy is an HTTP Handler that takes an incoming request and
// sends it to another server, proxying the response back to the
// client.
+//
+// ReverseProxy automatically sets the client IP as the value of the
+// X-Forwarded-For header.
+// If an X-Forwarded-For header already exists, the client IP is
+// appended to the existing values.
+// To prevent IP spoofing, be sure to delete any pre-existing
+// X-Forwarded-For header coming from the client or
+// an untrusted proxy.
type ReverseProxy struct {
// Director must be a function which modifies
// the request into a new request to be sent
diff --git a/libgo/go/net/http/omithttp2.go b/libgo/go/net/http/omithttp2.go
index a0b33e9..307d93a 100644
--- a/libgo/go/net/http/omithttp2.go
+++ b/libgo/go/net/http/omithttp2.go
@@ -36,6 +36,10 @@ type http2erringRoundTripper struct{}
func (http2erringRoundTripper) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) }
+type http2noDialH2RoundTripper struct{}
+
+func (http2noDialH2RoundTripper) RoundTrip(*Request) (*Response, error) { panic(noHTTP2) }
+
type http2noDialClientConnPool struct {
http2clientConnPool http2clientConnPool
}
diff --git a/libgo/go/net/http/request.go b/libgo/go/net/http/request.go
index 8dd9fe1..88fa093 100644
--- a/libgo/go/net/http/request.go
+++ b/libgo/go/net/http/request.go
@@ -1223,17 +1223,17 @@ func parsePostForm(r *Request) (vs url.Values, err error) {
// For all requests, ParseForm parses the raw query from the URL and updates
// r.Form.
//
-// For POST, PUT, and PATCH requests, it also parses the request body as a form
-// and puts the results into both r.PostForm and r.Form. Request body parameters
-// take precedence over URL query string values in r.Form.
+// For POST, PUT, and PATCH requests, it also reads the request body, parses it
+// as a form and puts the results into both r.PostForm and r.Form. Request body
+// parameters take precedence over URL query string values in r.Form.
+//
+// If the request Body's size has not already been limited by MaxBytesReader,
+// the size is capped at 10MB.
//
// For other HTTP methods, or when the Content-Type is not
// application/x-www-form-urlencoded, the request Body is not read, and
// r.PostForm is initialized to a non-nil, empty value.
//
-// If the request Body's size has not already been limited by MaxBytesReader,
-// the size is capped at 10MB.
-//
// ParseMultipartForm calls ParseForm automatically.
// ParseForm is idempotent.
func (r *Request) ParseForm() error {
diff --git a/libgo/go/net/http/transfer.go b/libgo/go/net/http/transfer.go
index 1d6a987..2e01a07 100644
--- a/libgo/go/net/http/transfer.go
+++ b/libgo/go/net/http/transfer.go
@@ -7,7 +7,6 @@ package http
import (
"bufio"
"bytes"
- "compress/gzip"
"errors"
"fmt"
"io"
@@ -467,34 +466,6 @@ func suppressedHeaders(status int) []string {
return nil
}
-// proxyingReadCloser is a composite type that accepts and proxies
-// io.Read and io.Close calls to its respective Reader and Closer.
-//
-// It is composed of:
-// a) a top-level reader e.g. the result of decompression
-// b) a symbolic Closer e.g. the result of decompression, the
-// original body and the connection itself.
-type proxyingReadCloser struct {
- io.Reader
- io.Closer
-}
-
-// multiCloser implements io.Closer and allows a bunch of io.Closer values
-// to all be closed once.
-// Example usage is with proxyingReadCloser if we are decompressing a response
-// body on the fly and would like to close both *gzip.Reader and underlying body.
-type multiCloser []io.Closer
-
-func (mc multiCloser) Close() error {
- var err error
- for _, c := range mc {
- if err1 := c.Close(); err1 != nil && err == nil {
- err = err1
- }
- }
- return err
-}
-
// msg is *Request or *Response.
func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
t := &transferReader{RequestMethod: "GET"}
@@ -572,7 +543,7 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
// Prepare body reader. ContentLength < 0 means chunked encoding
// or close connection when finished, since multipart is not supported yet
switch {
- case chunked(t.TransferEncoding) || implicitlyChunked(t.TransferEncoding):
+ case chunked(t.TransferEncoding):
if noResponseBodyExpected(t.RequestMethod) || !bodyAllowedForStatus(t.StatusCode) {
t.Body = NoBody
} else {
@@ -593,21 +564,6 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
}
}
- // Finally if "gzip" was one of the requested transfer-encodings,
- // we'll unzip the concatenated body/payload of the request.
- // TODO: As we support more transfer-encodings, extract
- // this code and apply the un-codings in reverse.
- if t.Body != NoBody && gzipped(t.TransferEncoding) {
- zr, err := gzip.NewReader(t.Body)
- if err != nil {
- return fmt.Errorf("http: failed to gunzip body: %v", err)
- }
- t.Body = &proxyingReadCloser{
- Reader: zr,
- Closer: multiCloser{zr, t.Body},
- }
- }
-
// Unify output
switch rr := msg.(type) {
case *Request:
@@ -627,41 +583,8 @@ func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
return nil
}
-// Checks whether chunked is the last part of the encodings stack
-func chunked(te []string) bool { return len(te) > 0 && te[len(te)-1] == "chunked" }
-
-// implicitlyChunked is a helper to check for implicity of chunked, because
-// RFC 7230 Section 3.3.1 says that the sender MUST apply chunked as the final
-// payload body to ensure that the message is framed for both the request
-// and the body. Since "identity" is incompatible with any other transformational
-// encoding cannot co-exist, the presence of "identity" will cause implicitlyChunked
-// to return false.
-func implicitlyChunked(te []string) bool {
- if len(te) == 0 { // No transfer-encodings passed in, so not implicitly chunked.
- return false
- }
- for _, tei := range te {
- if tei == "identity" {
- return false
- }
- }
- return true
-}
-
-func isGzipTransferEncoding(tei string) bool {
- // RFC 7230 4.2.3 requests that "x-gzip" SHOULD be considered the same as "gzip".
- return tei == "gzip" || tei == "x-gzip"
-}
-
-// Checks where either of "gzip" or "x-gzip" are contained in transfer encodings.
-func gzipped(te []string) bool {
- for _, tei := range te {
- if isGzipTransferEncoding(tei) {
- return true
- }
- }
- return false
-}
+// Checks whether chunked is part of the encodings stack
+func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
// Checks whether the encoding is explicitly "identity".
func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
@@ -697,47 +620,25 @@ func (t *transferReader) fixTransferEncoding() error {
encodings := strings.Split(raw[0], ",")
te := make([]string, 0, len(encodings))
-
- // When adding new encodings, please maintain the invariant:
- // if chunked encoding is present, it must always
- // come last and it must be applied only once.
- // See RFC 7230 Section 3.3.1 Transfer-Encoding.
- for i, encoding := range encodings {
+ // TODO: Even though we only support "identity" and "chunked"
+ // encodings, the loop below is designed with foresight. One
+ // invariant that must be maintained is that, if present,
+ // chunked encoding must always come first.
+ for _, encoding := range encodings {
encoding = strings.ToLower(strings.TrimSpace(encoding))
-
+ // "identity" encoding is not recorded
if encoding == "identity" {
- // "identity" should not be mixed with other transfer-encodings/compressions
- // because it means "no compression, no transformation".
- if len(encodings) != 1 {
- return &badStringError{`"identity" when present must be the only transfer encoding`, strings.Join(encodings, ",")}
- }
- // "identity" is not recorded.
break
}
-
- switch {
- case encoding == "chunked":
- // "chunked" MUST ALWAYS be the last
- // encoding as per the loop invariant.
- // That is:
- // Invalid: [chunked, gzip]
- // Valid: [gzip, chunked]
- if i+1 != len(encodings) {
- return &badStringError{"chunked must be applied only once, as the last encoding", strings.Join(encodings, ",")}
- }
- // Supported otherwise.
-
- case isGzipTransferEncoding(encoding):
- // Supported
-
- default:
+ if encoding != "chunked" {
return &unsupportedTEError{fmt.Sprintf("unsupported transfer encoding: %q", encoding)}
}
-
te = te[0 : len(te)+1]
te[len(te)-1] = encoding
}
-
+ if len(te) > 1 {
+ return &badStringError{"too many transfer encodings", strings.Join(te, ",")}
+ }
if len(te) > 0 {
// RFC 7230 3.3.2 says "A sender MUST NOT send a
// Content-Length header field in any message that
diff --git a/libgo/go/net/http/transfer_test.go b/libgo/go/net/http/transfer_test.go
index a8ce2d3..65009ee 100644
--- a/libgo/go/net/http/transfer_test.go
+++ b/libgo/go/net/http/transfer_test.go
@@ -7,7 +7,6 @@ package http
import (
"bufio"
"bytes"
- "compress/gzip"
"crypto/rand"
"fmt"
"io"
@@ -62,6 +61,7 @@ func TestFinalChunkedBodyReadEOF(t *testing.T) {
buf := make([]byte, len(want))
n, err := res.Body.Read(buf)
if n != len(want) || err != io.EOF {
+ t.Logf("body = %#v", res.Body)
t.Errorf("Read = %v, %v; want %d, EOF", n, err, len(want))
}
if string(buf) != want {
@@ -290,7 +290,7 @@ func TestFixTransferEncoding(t *testing.T) {
},
{
hdr: Header{"Transfer-Encoding": {"chunked, chunked", "identity", "chunked"}},
- wantErr: &badStringError{"chunked must be applied only once, as the last encoding", "chunked, chunked"},
+ wantErr: &badStringError{"too many transfer encodings", "chunked,chunked"},
},
{
hdr: Header{"Transfer-Encoding": {"chunked"}},
@@ -310,283 +310,3 @@ func TestFixTransferEncoding(t *testing.T) {
}
}
}
-
-func gzipIt(s string) string {
- buf := new(bytes.Buffer)
- gw := gzip.NewWriter(buf)
- gw.Write([]byte(s))
- gw.Close()
- return buf.String()
-}
-
-func TestUnitTestProxyingReadCloserClosesBody(t *testing.T) {
- var checker closeChecker
- buf := new(bytes.Buffer)
- buf.WriteString("Hello, Gophers!")
- prc := &proxyingReadCloser{
- Reader: buf,
- Closer: &checker,
- }
- prc.Close()
-
- read, err := ioutil.ReadAll(prc)
- if err != nil {
- t.Fatalf("Read error: %v", err)
- }
- if g, w := string(read), "Hello, Gophers!"; g != w {
- t.Errorf("Read mismatch: got %q want %q", g, w)
- }
-
- if checker.closed != true {
- t.Fatal("closeChecker.Close was never invoked")
- }
-}
-
-func TestGzipTransferEncoding_request(t *testing.T) {
- helloWorldGzipped := gzipIt("Hello, World!")
-
- tests := []struct {
- payload string
- wantErr string
- wantBody string
- }{
-
- {
- // The case of "chunked" properly applied as the last encoding
- // and a gzipped request payload that is streamed in 3 parts.
- payload: `POST / HTTP/1.1
-Host: golang.org
-Transfer-Encoding: gzip, chunked
-Content-Type: text/html; charset=UTF-8
-
-` + fmt.Sprintf("%02x\r\n%s\r\n%02x\r\n%s\r\n%02x\r\n%s\r\n0\r\n\r\n",
- 3, helloWorldGzipped[:3],
- 5, helloWorldGzipped[3:8],
- len(helloWorldGzipped)-8, helloWorldGzipped[8:]),
- wantBody: `Hello, World!`,
- },
-
- {
- // The request specifies "Transfer-Encoding: chunked" so its body must be left untouched.
- payload: `PUT / HTTP/1.1
-Host: golang.org
-Transfer-Encoding: chunked
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + fmt.Sprintf("%0x\r\n%s\r\n0\r\n\r\n", len(helloWorldGzipped), helloWorldGzipped),
- // We want that payload as it was sent.
- wantBody: helloWorldGzipped,
- },
-
- {
- // Valid request, the body doesn't have "Transfer-Encoding: chunked" but implicitly encoded
- // for chunking as per the advisory from RFC 7230 3.3.1 which advises for cases where.
- payload: `POST / HTTP/1.1
-Host: localhost
-Transfer-Encoding: gzip
-Content-Type: text/html; charset=UTF-8
-
-` + fmt.Sprintf("%0x\r\n%s\r\n0\r\n\r\n", len(helloWorldGzipped), helloWorldGzipped),
- wantBody: `Hello, World!`,
- },
-
- {
- // Invalid request, the body isn't chunked nor is the connection terminated immediately
- // hence invalid as per the advisory from RFC 7230 3.3.1 which advises for cases where
- // a Transfer-Encoding that isn't finally chunked is provided.
- payload: `PUT / HTTP/1.1
-Host: golang.org
-Transfer-Encoding: gzip
-Content-Length: 0
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-`,
- wantErr: `EOF`,
- },
-
- {
- // The case of chunked applied before another encoding.
- payload: `PUT / HTTP/1.1
-Location: golang.org
-Transfer-Encoding: chunked, gzip
-Content-Length: 0
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-`,
- wantErr: `chunked must be applied only once, as the last encoding "chunked, gzip"`,
- },
-
- {
- // The case of chunked properly applied as the
- // last encoding BUT with a bad "Content-Length".
- payload: `POST / HTTP/1.1
-Host: golang.org
-Transfer-Encoding: gzip, chunked
-Content-Length: 10
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + "0\r\n\r\n",
- wantErr: "EOF",
- },
- }
-
- for i, tt := range tests {
- req, err := ReadRequest(bufio.NewReader(strings.NewReader(tt.payload)))
- if tt.wantErr != "" {
- if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
- t.Errorf("test %d. Error mismatch\nGot: %v\nWant: %s", i, err, tt.wantErr)
- }
- continue
- }
-
- if err != nil {
- t.Errorf("test %d. Unexpected ReadRequest error: %v\nPayload:\n%s", i, err, tt.payload)
- continue
- }
-
- got, err := ioutil.ReadAll(req.Body)
- req.Body.Close()
- if err != nil {
- t.Errorf("test %d. Failed to read response body: %v", i, err)
- }
- if g, w := string(got), tt.wantBody; g != w {
- t.Errorf("test %d. Request body mimsatch\nGot:\n%s\n\nWant:\n%s", i, g, w)
- }
- }
-}
-
-func TestGzipTransferEncoding_response(t *testing.T) {
- helloWorldGzipped := gzipIt("Hello, World!")
-
- tests := []struct {
- payload string
- wantErr string
- wantBody string
- }{
-
- {
- // The case of "chunked" properly applied as the last encoding
- // and a gzipped payload that is streamed in 3 parts.
- payload: `HTTP/1.1 302 Found
-Location: https://golang.org/
-Transfer-Encoding: gzip, chunked
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + fmt.Sprintf("%02x\r\n%s\r\n%02x\r\n%s\r\n%02x\r\n%s\r\n0\r\n\r\n",
- 3, helloWorldGzipped[:3],
- 5, helloWorldGzipped[3:8],
- len(helloWorldGzipped)-8, helloWorldGzipped[8:]),
- wantBody: `Hello, World!`,
- },
-
- {
- // The response specifies "Transfer-Encoding: chunked" so response body must be left untouched.
- payload: `HTTP/1.1 302 Found
-Location: https://golang.org/
-Transfer-Encoding: chunked
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + fmt.Sprintf("%0x\r\n%s\r\n0\r\n\r\n", len(helloWorldGzipped), helloWorldGzipped),
- // We want that payload as it was sent.
- wantBody: helloWorldGzipped,
- },
-
- {
- // Valid response, the body doesn't have "Transfer-Encoding: chunked" but implicitly encoded
- // for chunking as per the advisory from RFC 7230 3.3.1 which advises for cases where.
- payload: `HTTP/1.1 302 Found
-Location: https://golang.org/
-Transfer-Encoding: gzip
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + fmt.Sprintf("%0x\r\n%s\r\n0\r\n\r\n", len(helloWorldGzipped), helloWorldGzipped),
- wantBody: `Hello, World!`,
- },
-
- {
- // Invalid response, the body isn't chunked nor is the connection terminated immediately
- // hence invalid as per the advisory from RFC 7230 3.3.1 which advises for cases where
- // a Transfer-Encoding that isn't finally chunked is provided.
- payload: `HTTP/1.1 302 Found
-Location: https://golang.org/
-Transfer-Encoding: gzip
-Content-Length: 0
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-`,
- wantErr: `EOF`,
- },
-
- {
- // The case of chunked applied before another encoding.
- payload: `HTTP/1.1 302 Found
-Location: https://golang.org/
-Transfer-Encoding: chunked, gzip
-Content-Length: 0
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-`,
- wantErr: `chunked must be applied only once, as the last encoding "chunked, gzip"`,
- },
-
- {
- // The case of chunked properly applied as the
- // last encoding BUT with a bad "Content-Length".
- payload: `HTTP/1.1 302 Found
-Location: https://golang.org/
-Transfer-Encoding: gzip, chunked
-Content-Length: 10
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + "0\r\n\r\n",
- wantErr: "EOF",
- },
-
- {
- // Including "identity" more than once.
- payload: `HTTP/1.1 200 OK
-Location: https://golang.org/
-Transfer-Encoding: identity, identity
-Content-Length: 0
-Connection: close
-Content-Type: text/html; charset=UTF-8
-
-` + "0\r\n\r\n",
- wantErr: `"identity" when present must be the only transfer encoding "identity, identity"`,
- },
- }
-
- for i, tt := range tests {
- res, err := ReadResponse(bufio.NewReader(strings.NewReader(tt.payload)), nil)
- if tt.wantErr != "" {
- if err == nil || !strings.Contains(err.Error(), tt.wantErr) {
- t.Errorf("test %d. Error mismatch\nGot: %v\nWant: %s", i, err, tt.wantErr)
- }
- continue
- }
-
- if err != nil {
- t.Errorf("test %d. Unexpected ReadResponse error: %v\nPayload:\n%s", i, err, tt.payload)
- continue
- }
-
- got, err := ioutil.ReadAll(res.Body)
- res.Body.Close()
- if err != nil {
- t.Errorf("test %d. Failed to read response body: %v", i, err)
- }
- if g, w := string(got), tt.wantBody; g != w {
- t.Errorf("test %d. Response body mimsatch\nGot:\n%s\n\nWant:\n%s", i, g, w)
- }
- }
-}
diff --git a/libgo/go/net/http/transport.go b/libgo/go/net/http/transport.go
index 64d8510..d0bfdb4 100644
--- a/libgo/go/net/http/transport.go
+++ b/libgo/go/net/http/transport.go
@@ -469,6 +469,17 @@ func (t *Transport) useRegisteredProtocol(req *Request) bool {
return true
}
+// alternateRoundTripper returns the alternate RoundTripper to use
+// for this request if the Request's URL scheme requires one,
+// or nil for the normal case of using the Transport.
+func (t *Transport) alternateRoundTripper(req *Request) RoundTripper {
+ if !t.useRegisteredProtocol(req) {
+ return nil
+ }
+ altProto, _ := t.altProto.Load().(map[string]RoundTripper)
+ return altProto[req.URL.Scheme]
+}
+
// roundTrip implements a RoundTripper over HTTP.
func (t *Transport) roundTrip(req *Request) (*Response, error) {
t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
@@ -500,12 +511,9 @@ func (t *Transport) roundTrip(req *Request) (*Response, error) {
}
}
- if t.useRegisteredProtocol(req) {
- altProto, _ := t.altProto.Load().(map[string]RoundTripper)
- if altRT := altProto[scheme]; altRT != nil {
- if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
- return resp, err
- }
+ if altRT := t.alternateRoundTripper(req); altRT != nil {
+ if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol {
+ return resp, err
}
}
if !isHTTP {
@@ -1559,15 +1567,16 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
if hdr == nil {
hdr = make(Header)
}
+ if pa := cm.proxyAuth(); pa != "" {
+ hdr = hdr.Clone()
+ hdr.Set("Proxy-Authorization", pa)
+ }
connectReq := &Request{
Method: "CONNECT",
URL: &url.URL{Opaque: cm.targetAddr},
Host: cm.targetAddr,
Header: hdr,
}
- if pa := cm.proxyAuth(); pa != "" {
- connectReq.Header.Set("Proxy-Authorization", pa)
- }
// If there's no done channel (no deadline or cancellation
// from the caller possible), at least set some (long)
diff --git a/libgo/go/net/http/transport_test.go b/libgo/go/net/http/transport_test.go
index 2256813..1e0334d 100644
--- a/libgo/go/net/http/transport_test.go
+++ b/libgo/go/net/http/transport_test.go
@@ -1550,6 +1550,44 @@ func TestTransportDialPreservesNetOpProxyError(t *testing.T) {
}
}
+// Issue 36431: calls to RoundTrip should not mutate t.ProxyConnectHeader.
+//
+// (A bug caused dialConn to instead write the per-request Proxy-Authorization
+// header through to the shared Header instance, introducing a data race.)
+func TestTransportProxyDialDoesNotMutateProxyConnectHeader(t *testing.T) {
+ setParallel(t)
+ defer afterTest(t)
+
+ proxy := httptest.NewTLSServer(NotFoundHandler())
+ defer proxy.Close()
+ c := proxy.Client()
+
+ tr := c.Transport.(*Transport)
+ tr.Proxy = func(*Request) (*url.URL, error) {
+ u, _ := url.Parse(proxy.URL)
+ u.User = url.UserPassword("aladdin", "opensesame")
+ return u, nil
+ }
+ h := tr.ProxyConnectHeader
+ if h == nil {
+ h = make(Header)
+ }
+ tr.ProxyConnectHeader = h.Clone()
+
+ req, err := NewRequest("GET", "https://golang.fake.tld/", nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = c.Do(req)
+ if err == nil {
+ t.Errorf("unexpected Get success")
+ }
+
+ if !reflect.DeepEqual(tr.ProxyConnectHeader, h) {
+ t.Errorf("tr.ProxyConnectHeader = %v; want %v", tr.ProxyConnectHeader, h)
+ }
+}
+
// TestTransportGzipRecursive sends a gzip quine and checks that the
// client gets the same value back. This is more cute than anything,
// but checks that we don't recurse forever, and checks that
@@ -6109,3 +6147,35 @@ func TestTransportDecrementConnWhenIdleConnRemoved(t *testing.T) {
t.Errorf("error occurred: %v", err)
}
}
+
+// Issue 36820
+// Test that we use the older backward compatible cancellation protocol
+// when a RoundTripper is registered via RegisterProtocol.
+func TestAltProtoCancellation(t *testing.T) {
+ defer afterTest(t)
+ tr := &Transport{}
+ c := &Client{
+ Transport: tr,
+ Timeout: time.Millisecond,
+ }
+ tr.RegisterProtocol("timeout", timeoutProto{})
+ _, err := c.Get("timeout://bar.com/path")
+ if err == nil {
+ t.Error("request unexpectedly succeeded")
+ } else if !strings.Contains(err.Error(), timeoutProtoErr.Error()) {
+ t.Errorf("got error %q, does not contain expected string %q", err, timeoutProtoErr)
+ }
+}
+
+var timeoutProtoErr = errors.New("canceled as expected")
+
+type timeoutProto struct{}
+
+func (timeoutProto) RoundTrip(req *Request) (*Response, error) {
+ select {
+ case <-req.Cancel:
+ return nil, timeoutProtoErr
+ case <-time.After(5 * time.Second):
+ return nil, errors.New("request was not canceled")
+ }
+}
diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go
index 8a41510..2bc5592 100644
--- a/libgo/go/net/lookup_test.go
+++ b/libgo/go/net/lookup_test.go
@@ -998,12 +998,16 @@ func TestConcurrentPreferGoResolversDial(t *testing.T) {
defer wg.Done()
_, err := r.LookupIPAddr(context.Background(), "google.com")
if err != nil {
- t.Fatalf("lookup failed for resolver %d: %q", index, err)
+ t.Errorf("lookup failed for resolver %d: %q", index, err)
}
}(resolver.Resolver, i)
}
wg.Wait()
+ if t.Failed() {
+ t.FailNow()
+ }
+
for i, resolver := range resolvers {
if !resolver.dialed {
t.Errorf("custom resolver %d not dialed during lookup", i)
@@ -1175,12 +1179,9 @@ func TestWithUnexpiredValuesPreserved(t *testing.T) {
}
}
-// Issue 31586: don't crash on null byte in name
+// Issue 31597: don't panic on null byte in name
func TestLookupNullByte(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
testenv.SkipFlakyNet(t)
- _, err := LookupHost("foo\x00bar") // used to crash on Windows
- if err == nil {
- t.Errorf("unexpected success")
- }
+ LookupHost("foo\x00bar") // check that it doesn't panic; it used to on Windows
}
diff --git a/libgo/go/net/net.go b/libgo/go/net/net.go
index 38c6b99..1d7e5e7 100644
--- a/libgo/go/net/net.go
+++ b/libgo/go/net/net.go
@@ -452,6 +452,7 @@ type OpError struct {
Addr Addr
// Err is the error that occurred during the operation.
+ // The Error method panics if the error is nil.
Err error
}
diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go
index 7995de7..9f8c827 100644
--- a/libgo/go/os/file.go
+++ b/libgo/go/os/file.go
@@ -204,6 +204,10 @@ func (f *File) WriteAt(b []byte, off int64) (n int, err error) {
// relative to the current offset, and 2 means relative to the end.
// It returns the new offset and an error, if any.
// The behavior of Seek on a file opened with O_APPEND is not specified.
+//
+// If f is a directory, the behavior of Seek varies by operating
+// system; you can seek to the beginning of the directory on Unix-like
+// operating systems, but not on Windows.
func (f *File) Seek(offset int64, whence int) (ret int64, err error) {
if err := f.checkValid("seek"); err != nil {
return 0, err
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go
index c9ed0a9..33d02ae 100644
--- a/libgo/go/reflect/all_test.go
+++ b/libgo/go/reflect/all_test.go
@@ -4864,6 +4864,9 @@ func TestStructOfExportRules(t *testing.T) {
if exported != test.exported {
t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported)
}
+ if field.PkgPath != test.field.PkgPath {
+ t.Errorf("test-%d: got PkgPath=%q want pkgPath=%q", i, field.PkgPath, test.field.PkgPath)
+ }
})
}
}
@@ -5327,6 +5330,24 @@ func TestStructOfTooManyFields(t *testing.T) {
}
}
+func TestStructOfDifferentPkgPath(t *testing.T) {
+ fields := []StructField{
+ {
+ Name: "f1",
+ PkgPath: "p1",
+ Type: TypeOf(int(0)),
+ },
+ {
+ Name: "f2",
+ PkgPath: "p2",
+ Type: TypeOf(int(0)),
+ },
+ }
+ shouldPanic(func() {
+ StructOf(fields)
+ })
+}
+
func TestChanOf(t *testing.T) {
// check construction and use of type not in binary
type T string
diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go
index a350674..9c003a4 100644
--- a/libgo/go/reflect/type.go
+++ b/libgo/go/reflect/type.go
@@ -1993,6 +1993,7 @@ func StructOf(fields []StructField) Type {
lastzero := uintptr(0)
repr = append(repr, "struct {"...)
+ pkgpath := ""
for i, field := range fields {
if field.Name == "" {
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
@@ -2003,11 +2004,18 @@ func StructOf(fields []StructField) Type {
if field.Type == nil {
panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
}
- f := runtimeStructField(field)
+ f, fpkgpath := runtimeStructField(field)
ft := f.typ
if ft.kind&kindGCProg != 0 {
hasGCProg = true
}
+ if fpkgpath != "" {
+ if pkgpath == "" {
+ pkgpath = fpkgpath
+ } else if pkgpath != fpkgpath {
+ panic("reflect.Struct: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
+ }
+ }
// Update string and hash
name := *f.name
@@ -2229,7 +2237,10 @@ func StructOf(fields []StructField) Type {
return addToCache(&typ.rtype)
}
-func runtimeStructField(field StructField) structField {
+// runtimeStructField takes a StructField value passed to StructOf and
+// returns both the corresponding internal representation, of type
+// structField, and the pkgpath value to use for this field.
+func runtimeStructField(field StructField) (structField, string) {
if field.Anonymous && field.PkgPath != "" {
panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
}
@@ -2263,13 +2274,14 @@ func runtimeStructField(field StructField) structField {
s := field.PkgPath
pkgPath = &s
}
- return structField{
+ f := structField{
name: name,
pkgPath: pkgPath,
typ: field.Type.common(),
tag: tag,
offsetEmbed: offsetEmbed,
}
+ return f, field.PkgPath
}
// typeptrdata returns the length in bytes of the prefix of t
diff --git a/libgo/go/runtime/chan.go b/libgo/go/runtime/chan.go
index 549e566..ec8252b 100644
--- a/libgo/go/runtime/chan.go
+++ b/libgo/go/runtime/chan.go
@@ -133,21 +133,6 @@ func chanbuf(c *hchan, i uint) unsafe.Pointer {
return add(c.buf, uintptr(i)*uintptr(c.elemsize))
}
-// full reports whether a send on c would block (that is, the channel is full).
-// It uses a single word-sized read of mutable state, so although
-// the answer is instantaneously true, the correct answer may have changed
-// by the time the calling function receives the return value.
-func full(c *hchan) bool {
- // c.dataqsiz is immutable (never written after the channel is created)
- // so it is safe to read at any time during channel operation.
- if c.dataqsiz == 0 {
- // Assumes that a pointer read is relaxed-atomic.
- return c.recvq.first == nil
- }
- // Assumes that a uint read is relaxed-atomic.
- return c.qcount == c.dataqsiz
-}
-
// entry point for c <- x from compiled code
//go:nosplit
func chansend1(c *hchan, elem unsafe.Pointer) {
@@ -192,7 +177,7 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
//
// After observing that the channel is not closed, we observe that the channel is
// not ready for sending. Each of these observations is a single word-sized read
- // (first c.closed and second full()).
+ // (first c.closed and second c.recvq.first or c.qcount depending on kind of channel).
// Because a closed channel cannot transition from 'ready for sending' to
// 'not ready for sending', even if the channel is closed between the two observations,
// they imply a moment between the two when the channel was both not yet closed
@@ -201,10 +186,9 @@ func chansend(c *hchan, ep unsafe.Pointer, block bool, callerpc uintptr) bool {
//
// It is okay if the reads are reordered here: if we observe that the channel is not
// ready for sending and then observe that it is not closed, that implies that the
- // channel wasn't closed during the first observation. However, nothing here
- // guarantees forward progress. We rely on the side effects of lock release in
- // chanrecv() and closechan() to update this thread's view of c.closed and full().
- if !block && c.closed == 0 && full(c) {
+ // channel wasn't closed during the first observation.
+ if !block && c.closed == 0 && ((c.dataqsiz == 0 && c.recvq.first == nil) ||
+ (c.dataqsiz > 0 && c.qcount == c.dataqsiz)) {
return false
}
@@ -434,16 +418,6 @@ func closechan(c *hchan) {
}
}
-// empty reports whether a read from c would block (that is, the channel is
-// empty). It uses a single atomic read of mutable state.
-func empty(c *hchan) bool {
- // c.dataqsiz is immutable.
- if c.dataqsiz == 0 {
- return atomic.Loadp(unsafe.Pointer(&c.sendq.first)) == nil
- }
- return atomic.Loaduint(&c.qcount) == 0
-}
-
// entry points for <- c from compiled code
//go:nosplit
func chanrecv1(c *hchan, elem unsafe.Pointer) {
@@ -484,33 +458,21 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
}
// Fast path: check for failed non-blocking operation without acquiring the lock.
- if !block && empty(c) {
- // After observing that the channel is not ready for receiving, we observe whether the
- // channel is closed.
- //
- // Reordering of these checks could lead to incorrect behavior when racing with a close.
- // For example, if the channel was open and not empty, was closed, and then drained,
- // reordered reads could incorrectly indicate "open and empty". To prevent reordering,
- // we use atomic loads for both checks, and rely on emptying and closing to happen in
- // separate critical sections under the same lock. This assumption fails when closing
- // an unbuffered channel with a blocked send, but that is an error condition anyway.
- if atomic.Load(&c.closed) == 0 {
- // Because a channel cannot be reopened, the later observation of the channel
- // being not closed implies that it was also not closed at the moment of the
- // first observation. We behave as if we observed the channel at that moment
- // and report that the receive cannot proceed.
- return
- }
- // The channel is irreversibly closed. Re-check whether the channel has any pending data
- // to receive, which could have arrived between the empty and closed checks above.
- // Sequential consistency is also required here, when racing with such a send.
- if empty(c) {
- // The channel is irreversibly closed and empty.
- if ep != nil {
- typedmemclr(c.elemtype, ep)
- }
- return true, false
- }
+ //
+ // After observing that the channel is not ready for receiving, we observe that the
+ // channel is not closed. Each of these observations is a single word-sized read
+ // (first c.sendq.first or c.qcount, and second c.closed).
+ // Because a channel cannot be reopened, the later observation of the channel
+ // being not closed implies that it was also not closed at the moment of the
+ // first observation. We behave as if we observed the channel at that moment
+ // and report that the receive cannot proceed.
+ //
+ // The order of operations is important here: reversing the operations can lead to
+ // incorrect behavior when racing with a close.
+ if !block && (c.dataqsiz == 0 && c.sendq.first == nil ||
+ c.dataqsiz > 0 && atomic.Loaduint(&c.qcount) == 0) &&
+ atomic.Load(&c.closed) == 0 {
+ return
}
var t0 int64
diff --git a/libgo/go/runtime/chan_test.go b/libgo/go/runtime/chan_test.go
index ac81d40..c194781 100644
--- a/libgo/go/runtime/chan_test.go
+++ b/libgo/go/runtime/chan_test.go
@@ -1132,20 +1132,6 @@ func BenchmarkChanPopular(b *testing.B) {
wg.Wait()
}
-func BenchmarkChanClosed(b *testing.B) {
- c := make(chan struct{})
- close(c)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- select {
- case <-c:
- default:
- b.Error("Unreachable")
- }
- }
- })
-}
-
var (
alwaysFalse = false
workSink = 0
diff --git a/libgo/go/runtime/checkptr.go b/libgo/go/runtime/checkptr.go
index f478ddd..974f0a0 100644
--- a/libgo/go/runtime/checkptr.go
+++ b/libgo/go/runtime/checkptr.go
@@ -8,45 +8,22 @@ package runtime
import "unsafe"
-type ptrAlignError struct {
- ptr unsafe.Pointer
- elem *_type
- n uintptr
-}
-
-func (e ptrAlignError) RuntimeError() {}
-
-func (e ptrAlignError) Error() string {
- return "runtime error: unsafe pointer conversion"
-}
-
func checkptrAlignment(p unsafe.Pointer, elem *_type, n uintptr) {
// Check that (*[n]elem)(p) is appropriately aligned.
// TODO(mdempsky): What about fieldAlign?
if uintptr(p)&(uintptr(elem.align)-1) != 0 {
- panic(ptrAlignError{p, elem, n})
+ throw("checkptr: unsafe pointer conversion")
}
// Check that (*[n]elem)(p) doesn't straddle multiple heap objects.
if size := n * elem.size; size > 1 && checkptrBase(p) != checkptrBase(add(p, size-1)) {
- panic(ptrAlignError{p, elem, n})
+ throw("checkptr: unsafe pointer conversion")
}
}
-type ptrArithError struct {
- ptr unsafe.Pointer
- originals []unsafe.Pointer
-}
-
-func (e ptrArithError) RuntimeError() {}
-
-func (e ptrArithError) Error() string {
- return "runtime error: unsafe pointer arithmetic"
-}
-
func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
if 0 < uintptr(p) && uintptr(p) < minLegalPointer {
- panic(ptrArithError{p, originals})
+ throw("checkptr: unsafe pointer arithmetic")
}
// Check that if the computed pointer p points into a heap
@@ -63,7 +40,7 @@ func checkptrArithmetic(p unsafe.Pointer, originals []unsafe.Pointer) {
}
}
- panic(ptrArithError{p, originals})
+ throw("checkptr: unsafe pointer arithmetic")
}
// checkptrBase returns the base address for the allocation containing
diff --git a/libgo/go/runtime/checkptr_test.go b/libgo/go/runtime/checkptr_test.go
new file mode 100644
index 0000000..ab3058f
--- /dev/null
+++ b/libgo/go/runtime/checkptr_test.go
@@ -0,0 +1,50 @@
+// Copyright 2020 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 runtime_test
+
+import (
+ "internal/testenv"
+ "os/exec"
+ "runtime"
+ "strings"
+ "testing"
+)
+
+func TestCheckPtr(t *testing.T) {
+ if runtime.Compiler == "gccgo" {
+ t.Skip("gccgo does not have -d=checkptr")
+ }
+ t.Parallel()
+ testenv.MustHaveGoRun(t)
+
+ exe, err := buildTestProg(t, "testprog", "-gcflags=all=-d=checkptr=1")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ testCases := []struct {
+ cmd string
+ want string
+ }{
+ {"CheckPtrAlignment", "fatal error: checkptr: unsafe pointer conversion\n"},
+ {"CheckPtrArithmetic", "fatal error: checkptr: unsafe pointer arithmetic\n"},
+ {"CheckPtrSize", "fatal error: checkptr: unsafe pointer conversion\n"},
+ {"CheckPtrSmall", "fatal error: checkptr: unsafe pointer arithmetic\n"},
+ }
+
+ for _, tc := range testCases {
+ tc := tc
+ t.Run(tc.cmd, func(t *testing.T) {
+ t.Parallel()
+ got, err := testenv.CleanCmdEnv(exec.Command(exe, tc.cmd)).CombinedOutput()
+ if err != nil {
+ t.Log(err)
+ }
+ if !strings.HasPrefix(string(got), tc.want) {
+ t.Errorf("output:\n%s\n\nwant output starting with: %s", got, tc.want)
+ }
+ })
+ }
+}
diff --git a/libgo/go/runtime/debug.go b/libgo/go/runtime/debug.go
index 1202e36..e480466 100644
--- a/libgo/go/runtime/debug.go
+++ b/libgo/go/runtime/debug.go
@@ -26,12 +26,12 @@ func GOMAXPROCS(n int) int {
return ret
}
- stopTheWorldGC("GOMAXPROCS")
+ stopTheWorld("GOMAXPROCS")
// newprocs will be processed by startTheWorld
newprocs = int32(n)
- startTheWorldGC()
+ startTheWorld()
return ret
}
diff --git a/libgo/go/runtime/export_test.go b/libgo/go/runtime/export_test.go
index 9a977d8..b60c19b 100644
--- a/libgo/go/runtime/export_test.go
+++ b/libgo/go/runtime/export_test.go
@@ -45,6 +45,9 @@ var NetpollGenericInit = netpollGenericInit
var ParseRelease = parseRelease
+var Memmove = memmove
+var MemclrNoHeapPointers = memclrNoHeapPointers
+
const PreemptMSupported = preemptMSupported
type LFNode struct {
@@ -573,6 +576,7 @@ const (
PageSize = pageSize
PallocChunkPages = pallocChunkPages
PageAlloc64Bit = pageAlloc64Bit
+ PallocSumBytes = pallocSumBytes
)
// Expose pallocSum for testing.
diff --git a/libgo/go/runtime/extern.go b/libgo/go/runtime/extern.go
index e2e601f..96af606 100644
--- a/libgo/go/runtime/extern.go
+++ b/libgo/go/runtime/extern.go
@@ -78,21 +78,6 @@ It is a comma-separated list of name=val pairs setting these named variables:
If the line ends with "(forced)", this GC was forced by a
runtime.GC() call.
- Setting gctrace to any value > 0 also causes the garbage collector
- to emit a summary when memory is released back to the system.
- This process of returning memory to the system is called scavenging.
- The format of this summary is subject to change.
- Currently it is:
- scvg#: # MB released printed only if non-zero
- scvg#: inuse: # idle: # sys: # released: # consumed: # (MB)
- where the fields are as follows:
- scvg# the scavenge cycle number, incremented at each scavenge
- inuse: # MB used or partially used spans
- idle: # MB spans pending scavenging
- sys: # MB mapped from the system
- released: # MB released to the system
- consumed: # MB allocated from the system
-
madvdontneed: setting madvdontneed=1 will use MADV_DONTNEED
instead of MADV_FREE on Linux when returning memory to the
kernel. This is less efficient, but causes RSS numbers to drop
@@ -112,6 +97,19 @@ It is a comma-separated list of name=val pairs setting these named variables:
scavenge: scavenge=1 enables debugging mode of heap scavenger.
+ scavtrace: setting scavtrace=1 causes the runtime to emit a single line to standard
+ error, roughly once per GC cycle, summarizing the amount of work done by the
+ scavenger as well as the total amount of memory returned to the operating system
+ and an estimate of physical memory utilization. The format of this line is subject
+ to change, but currently it is:
+ scav # KiB work, # KiB total, #% util
+ where the fields are as follows:
+ # KiB work the amount of memory returned to the OS since the last scav line
+ # KiB total how much of the heap at this point in time has been released to the OS
+ #% util the fraction of all unscavenged memory which is in-use
+ If the line ends with "(forced)", then scavenging was forced by a
+ debug.FreeOSMemory() call.
+
scheddetail: setting schedtrace=X and scheddetail=1 causes the scheduler to emit
detailed multiline info every X milliseconds, describing state of the scheduler,
processors, threads and goroutines.
diff --git a/libgo/go/runtime/gcinfo_test.go b/libgo/go/runtime/gcinfo_test.go
index fc24f04..ddbe5dd 100644
--- a/libgo/go/runtime/gcinfo_test.go
+++ b/libgo/go/runtime/gcinfo_test.go
@@ -165,7 +165,7 @@ func infoBigStruct() []byte {
typeScalar, typeScalar, typeScalar, typeScalar, // t int; y uint16; u uint64
typePointer, typeScalar, // i string
}
- case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le", "s390x", "wasm":
+ case "arm64", "amd64", "mips64", "mips64le", "ppc64", "ppc64le", "riscv64", "s390x", "wasm":
return []byte{
typePointer, // q *int
typeScalar, typeScalar, typeScalar, // w byte; e [17]byte
diff --git a/libgo/go/runtime/hash64.go b/libgo/go/runtime/hash64.go
index cff663a..704bbe6 100644
--- a/libgo/go/runtime/hash64.go
+++ b/libgo/go/runtime/hash64.go
@@ -6,7 +6,7 @@
// xxhash: https://code.google.com/p/xxhash/
// cityhash: https://code.google.com/p/cityhash/
-// +build amd64 amd64p32 arm64 mips64 mips64le ppc64 ppc64le s390x wasm alpha arm64be ia64 mips64p32 mips64p32le sparc64 riscv64
+// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm alpha amd64p32 arm64be ia64 mips64p32 mips64p32le sparc64
package runtime
diff --git a/libgo/go/runtime/lfstack_64bit.go b/libgo/go/runtime/lfstack_64bit.go
index de40a00..af9e7d1 100644
--- a/libgo/go/runtime/lfstack_64bit.go
+++ b/libgo/go/runtime/lfstack_64bit.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.
-// +build amd64 arm64 mips64 mips64le ppc64 ppc64le s390x wasm arm64be alpha sparc64 ia64 riscv64
+// +build amd64 arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x wasm arm64be alpha sparc64 ia64
package runtime
diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go
index fda2273..35ace7f 100644
--- a/libgo/go/runtime/malloc.go
+++ b/libgo/go/runtime/malloc.go
@@ -513,6 +513,7 @@ func mallocinit() {
// allocation at 0x40 << 32 because when using 4k pages with 3-level
// translation buffers, the user address space is limited to 39 bits
// On darwin/arm64, the address space is even smaller.
+ //
// On AIX, mmaps starts at 0x0A00000000000000 for 64-bit.
// processes.
for i := 0x7f; i >= 0; i-- {
diff --git a/libgo/go/runtime/malloc_test.go b/libgo/go/runtime/malloc_test.go
index bd30bc1..45555ee 100644
--- a/libgo/go/runtime/malloc_test.go
+++ b/libgo/go/runtime/malloc_test.go
@@ -206,14 +206,6 @@ type acLink struct {
var arenaCollisionSink []*acLink
func TestArenaCollision(t *testing.T) {
- if GOOS == "darwin" && race.Enabled {
- // Skip this test on Darwin in race mode because Darwin 10.10 has
- // issues following arena hints and runs out of them in race mode, so
- // MAP_FIXED is used to ensure we keep the heap in the memory region the
- // race detector expects.
- // TODO(mknyszek): Delete this when Darwin 10.10 is no longer supported.
- t.Skip("disabled on Darwin with race mode since MAP_FIXED is used")
- }
testenv.MustHaveExec(t)
// Test that mheap.sysAlloc handles collisions with other
diff --git a/libgo/go/runtime/memmove_test.go b/libgo/go/runtime/memmove_test.go
index 0b2e191..396c130 100644
--- a/libgo/go/runtime/memmove_test.go
+++ b/libgo/go/runtime/memmove_test.go
@@ -11,7 +11,9 @@ import (
"internal/race"
"internal/testenv"
. "runtime"
+ "sync/atomic"
"testing"
+ "unsafe"
)
func TestMemmove(t *testing.T) {
@@ -206,6 +208,71 @@ func cmpb(a, b []byte) int {
return l
}
+// Ensure that memmove writes pointers atomically, so the GC won't
+// observe a partially updated pointer.
+func TestMemmoveAtomicity(t *testing.T) {
+ if race.Enabled {
+ t.Skip("skip under the race detector -- this test is intentionally racy")
+ }
+
+ var x int
+
+ for _, backward := range []bool{true, false} {
+ for _, n := range []int{3, 4, 5, 6, 7, 8, 9, 10, 15, 25, 49} {
+ n := n
+
+ // test copying [N]*int.
+ sz := uintptr(n * PtrSize)
+ name := fmt.Sprint(sz)
+ if backward {
+ name += "-backward"
+ } else {
+ name += "-forward"
+ }
+ t.Run(name, func(t *testing.T) {
+ // Use overlapping src and dst to force forward/backward copy.
+ var s [100]*int
+ src := s[n-1 : 2*n-1]
+ dst := s[:n]
+ if backward {
+ src, dst = dst, src
+ }
+ for i := range src {
+ src[i] = &x
+ }
+ for i := range dst {
+ dst[i] = nil
+ }
+
+ var ready uint32
+ go func() {
+ sp := unsafe.Pointer(&src[0])
+ dp := unsafe.Pointer(&dst[0])
+ atomic.StoreUint32(&ready, 1)
+ for i := 0; i < 10000; i++ {
+ Memmove(dp, sp, sz)
+ MemclrNoHeapPointers(dp, sz)
+ }
+ atomic.StoreUint32(&ready, 2)
+ }()
+
+ for atomic.LoadUint32(&ready) == 0 {
+ Gosched()
+ }
+
+ for atomic.LoadUint32(&ready) != 2 {
+ for i := range dst {
+ p := dst[i]
+ if p != nil && p != &x {
+ t.Fatalf("got partially updated pointer %p at dst[%d], want either nil or %p", p, i, &x)
+ }
+ }
+ }
+ })
+ }
+ }
+}
+
func benchmarkSizes(b *testing.B, sizes []int, fn func(b *testing.B, n int)) {
for _, n := range sizes {
b.Run(fmt.Sprint(n), func(b *testing.B) {
diff --git a/libgo/go/runtime/mgc.go b/libgo/go/runtime/mgc.go
index b0040f9..8ded306 100644
--- a/libgo/go/runtime/mgc.go
+++ b/libgo/go/runtime/mgc.go
@@ -1271,7 +1271,6 @@ func gcStart(trigger gcTrigger) {
}
// Ok, we're doing it! Stop everybody else
- semacquire(&gcsema)
semacquire(&worldsema)
if trace.enabled {
@@ -1370,13 +1369,6 @@ func gcStart(trigger gcTrigger) {
work.pauseNS += now - work.pauseStart
work.tMark = now
})
-
- // Release the world sema before Gosched() in STW mode
- // because we will need to reacquire it later but before
- // this goroutine becomes runnable again, and we could
- // self-deadlock otherwise.
- semrelease(&worldsema)
-
// In STW mode, we could block the instant systemstack
// returns, so don't do anything important here. Make sure we
// block rather than returning to user code.
@@ -1446,10 +1438,6 @@ top:
return
}
- // forEachP needs worldsema to execute, and we'll need it to
- // stop the world later, so acquire worldsema now.
- semacquire(&worldsema)
-
// Flush all local buffers and collect flushedWork flags.
gcMarkDoneFlushed = 0
systemstack(func() {
@@ -1510,7 +1498,6 @@ top:
// work to do. Keep going. It's possible the
// transition condition became true again during the
// ragged barrier, so re-check it.
- semrelease(&worldsema)
goto top
}
@@ -1587,7 +1574,6 @@ top:
now := startTheWorldWithSema(true)
work.pauseNS += now - work.pauseStart
})
- semrelease(&worldsema)
goto top
}
}
@@ -1802,7 +1788,6 @@ func gcMarkTermination(nextTriggerRatio float64) {
}
semrelease(&worldsema)
- semrelease(&gcsema)
// Careful: another GC cycle may start now.
releasem(mp)
diff --git a/libgo/go/runtime/mgcscavenge.go b/libgo/go/runtime/mgcscavenge.go
index f3856db..3b60b3d 100644
--- a/libgo/go/runtime/mgcscavenge.go
+++ b/libgo/go/runtime/mgcscavenge.go
@@ -80,6 +80,17 @@ const (
// maxPagesPerPhysPage is the maximum number of supported runtime pages per
// physical page, based on maxPhysPageSize.
maxPagesPerPhysPage = maxPhysPageSize / pageSize
+
+ // scavengeCostRatio is the approximate ratio between the costs of using previously
+ // scavenged memory and scavenging memory.
+ //
+ // For most systems the cost of scavenging greatly outweighs the costs
+ // associated with using scavenged memory, making this constant 0. On other systems
+ // (especially ones where "sysUsed" is not just a no-op) this cost is non-trivial.
+ //
+ // This ratio is used as part of multiplicative factor to help the scavenger account
+ // for the additional costs of using scavenged memory in its pacing.
+ scavengeCostRatio = 0.7 * sys.GoosDarwin
)
// heapRetained returns an estimate of the current heap RSS.
@@ -248,7 +259,7 @@ func bgscavenge(c chan int) {
released := uintptr(0)
// Time in scavenging critical section.
- crit := int64(0)
+ crit := float64(0)
// Run on the system stack since we grab the heap lock,
// and a stack growth with the heap lock means a deadlock.
@@ -266,16 +277,10 @@ func bgscavenge(c chan int) {
// Scavenge one page, and measure the amount of time spent scavenging.
start := nanotime()
released = mheap_.pages.scavengeOne(physPageSize, false)
- crit = nanotime() - start
+ atomic.Xadduintptr(&mheap_.pages.scavReleased, released)
+ crit = float64(nanotime() - start)
})
- if debug.gctrace > 0 {
- if released > 0 {
- print("scvg: ", released>>10, " KB released\n")
- }
- print("scvg: inuse: ", memstats.heap_inuse>>20, ", idle: ", memstats.heap_idle>>20, ", sys: ", memstats.heap_sys>>20, ", released: ", memstats.heap_released>>20, ", consumed: ", (memstats.heap_sys-memstats.heap_released)>>20, " (MB)\n")
- }
-
if released == 0 {
lock(&scavenge.lock)
scavenge.parked = true
@@ -283,6 +288,14 @@ func bgscavenge(c chan int) {
continue
}
+ // Multiply the critical time by 1 + the ratio of the costs of using
+ // scavenged memory vs. scavenging memory. This forces us to pay down
+ // the cost of reusing this memory eagerly by sleeping for a longer period
+ // of time and scavenging less frequently. More concretely, we avoid situations
+ // where we end up scavenging so often that we hurt allocation performance
+ // because of the additional overheads of using scavenged memory.
+ crit *= 1 + scavengeCostRatio
+
// If we spent more than 10 ms (for example, if the OS scheduled us away, or someone
// put their machine to sleep) in the critical section, bound the time we use to
// calculate at 10 ms to avoid letting the sleep time get arbitrarily high.
@@ -298,13 +311,13 @@ func bgscavenge(c chan int) {
// much, then scavengeEMWA < idealFraction, so we'll adjust the sleep time
// down.
adjust := scavengeEWMA / idealFraction
- sleepTime := int64(adjust * float64(crit) / (scavengePercent / 100.0))
+ sleepTime := int64(adjust * crit / (scavengePercent / 100.0))
// Go to sleep.
slept := scavengeSleep(sleepTime)
// Compute the new ratio.
- fraction := float64(crit) / float64(crit+slept)
+ fraction := crit / (crit + float64(slept))
// Set a lower bound on the fraction.
// Due to OS-related anomalies we may "sleep" for an inordinate amount
@@ -348,12 +361,39 @@ func (s *pageAlloc) scavenge(nbytes uintptr, locked bool) uintptr {
return released
}
+// printScavTrace prints a scavenge trace line to standard error.
+//
+// released should be the amount of memory released since the last time this
+// was called, and forced indicates whether the scavenge was forced by the
+// application.
+func printScavTrace(released uintptr, forced bool) {
+ printlock()
+ print("scav ",
+ released>>10, " KiB work, ",
+ atomic.Load64(&memstats.heap_released)>>10, " KiB total, ",
+ (atomic.Load64(&memstats.heap_inuse)*100)/heapRetained(), "% util",
+ )
+ if forced {
+ print(" (forced)")
+ }
+ println()
+ printunlock()
+}
+
// resetScavengeAddr sets the scavenge start address to the top of the heap's
// address space. This should be called each time the scavenger's pacing
// changes.
//
// s.mheapLock must be held.
func (s *pageAlloc) resetScavengeAddr() {
+ released := atomic.Loaduintptr(&s.scavReleased)
+ if debug.scavtrace > 0 {
+ printScavTrace(released, false)
+ }
+ // Subtract from scavReleased instead of just setting it to zero because
+ // the scavenger could have increased scavReleased concurrently with the
+ // load above, and we may miss an update by just blindly zeroing the field.
+ atomic.Xadduintptr(&s.scavReleased, -released)
s.scavAddr = chunkBase(s.end) - 1
}
@@ -415,7 +455,10 @@ func (s *pageAlloc) scavengeOne(max uintptr, locked bool) uintptr {
// Check the chunk containing the scav addr, starting at the addr
// and see if there are any free and unscavenged pages.
- if s.summary[len(s.summary)-1][ci].max() >= uint(minPages) {
+ //
+ // Only check this if s.scavAddr is covered by any address range
+ // in s.inUse, so that we know our check of the summary is safe.
+ if s.inUse.contains(s.scavAddr) && s.summary[len(s.summary)-1][ci].max() >= uint(minPages) {
// We only bother looking for a candidate if there at least
// minPages free pages at all. It's important that we only
// continue if the summary says we can because that's how
diff --git a/libgo/go/runtime/mgcscavenge_test.go b/libgo/go/runtime/mgcscavenge_test.go
index 518d5ab..58f9e3a 100644
--- a/libgo/go/runtime/mgcscavenge_test.go
+++ b/libgo/go/runtime/mgcscavenge_test.go
@@ -272,6 +272,9 @@ func TestPallocDataFindScavengeCandidate(t *testing.T) {
// Tests end-to-end scavenging on a pageAlloc.
func TestPageAllocScavenge(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
type test struct {
request, expect uintptr
}
@@ -279,12 +282,13 @@ func TestPageAllocScavenge(t *testing.T) {
if minPages < 1 {
minPages = 1
}
- tests := map[string]struct {
+ type setup struct {
beforeAlloc map[ChunkIdx][]BitRange
beforeScav map[ChunkIdx][]BitRange
expect []test
afterScav map[ChunkIdx][]BitRange
- }{
+ }
+ tests := map[string]setup{
"AllFreeUnscavExhaust": {
beforeAlloc: map[ChunkIdx][]BitRange{
BaseChunkIdx: {},
@@ -393,6 +397,26 @@ func TestPageAllocScavenge(t *testing.T) {
},
},
}
+ if PageAlloc64Bit != 0 {
+ tests["ScavAllVeryDiscontiguous"] = setup{
+ beforeAlloc: map[ChunkIdx][]BitRange{
+ BaseChunkIdx: {},
+ BaseChunkIdx + 0x1000: {},
+ },
+ beforeScav: map[ChunkIdx][]BitRange{
+ BaseChunkIdx: {},
+ BaseChunkIdx + 0x1000: {},
+ },
+ expect: []test{
+ {^uintptr(0), 2 * PallocChunkPages * PageSize},
+ {^uintptr(0), 0},
+ },
+ afterScav: map[ChunkIdx][]BitRange{
+ BaseChunkIdx: {{0, PallocChunkPages}},
+ BaseChunkIdx + 0x1000: {{0, PallocChunkPages}},
+ },
+ }
+ }
for name, v := range tests {
v := v
runTest := func(t *testing.T, locked bool) {
diff --git a/libgo/go/runtime/mheap.go b/libgo/go/runtime/mheap.go
index f40589a..c40c9e2 100644
--- a/libgo/go/runtime/mheap.go
+++ b/libgo/go/runtime/mheap.go
@@ -70,7 +70,7 @@ type mheap struct {
// on the swept stack.
sweepSpans [2]gcSweepBuf
- _ uint32 // align uint64 fields on 32-bit for atomics
+ // _ uint32 // align uint64 fields on 32-bit for atomics
// Proportional sweep
//
@@ -786,7 +786,9 @@ func (h *mheap) reclaim(npage uintptr) {
// reclaimChunk sweeps unmarked spans that start at page indexes [pageIdx, pageIdx+n).
// It returns the number of pages returned to the heap.
//
-// h.lock must be held and the caller must be non-preemptible.
+// h.lock must be held and the caller must be non-preemptible. Note: h.lock may be
+// temporarily unlocked and re-locked in order to do sweeping or if tracing is
+// enabled.
func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr {
// The heap lock must be held because this accesses the
// heapArena.spans arrays using potentially non-live pointers.
@@ -842,8 +844,10 @@ func (h *mheap) reclaimChunk(arenas []arenaIdx, pageIdx, n uintptr) uintptr {
n -= uintptr(len(inUse) * 8)
}
if trace.enabled {
+ unlock(&h.lock)
// Account for pages scanned but not reclaimed.
traceGCSweepSpan((n0 - nFreed) * pageSize)
+ lock(&h.lock)
}
return nFreed
}
@@ -1430,11 +1434,8 @@ func (h *mheap) scavengeAll() {
unlock(&h.lock)
gp.m.mallocing--
- if debug.gctrace > 0 {
- if released > 0 {
- print("forced scvg: ", released>>20, " MB released\n")
- }
- print("forced scvg: inuse: ", memstats.heap_inuse>>20, ", idle: ", memstats.heap_idle>>20, ", sys: ", memstats.heap_sys>>20, ", released: ", memstats.heap_released>>20, ", consumed: ", (memstats.heap_sys-memstats.heap_released)>>20, " (MB)\n")
+ if debug.scavtrace > 0 {
+ printScavTrace(released, true)
}
}
diff --git a/libgo/go/runtime/mkpreempt.go b/libgo/go/runtime/mkpreempt.go
index 615ec18..64e2207 100644
--- a/libgo/go/runtime/mkpreempt.go
+++ b/libgo/go/runtime/mkpreempt.go
@@ -83,6 +83,7 @@ var arches = map[string]func(){
"mips64x": func() { genMIPS(true) },
"mipsx": func() { genMIPS(false) },
"ppc64x": genPPC64,
+ "riscv64": genRISCV64,
"s390x": genS390X,
"wasm": genWasm,
}
@@ -478,6 +479,11 @@ func genPPC64() {
p("JMP (CTR)")
}
+func genRISCV64() {
+ p("// No async preemption on riscv64 - see issue 36711")
+ p("UNDEF")
+}
+
func genS390X() {
// Add integer registers R0-R12
// R13 (g), R14 (LR), R15 (SP) are special, and not saved here.
diff --git a/libgo/go/runtime/mpagealloc.go b/libgo/go/runtime/mpagealloc.go
index 572e6a9..bb751f1 100644
--- a/libgo/go/runtime/mpagealloc.go
+++ b/libgo/go/runtime/mpagealloc.go
@@ -225,7 +225,9 @@ type pageAlloc struct {
// the bitmaps align better on zero-values.
chunks [1 << pallocChunksL1Bits]*[1 << pallocChunksL2Bits]pallocData
- // The address to start an allocation search with.
+ // The address to start an allocation search with. It must never
+ // point to any memory that is not contained in inUse, i.e.
+ // inUse.contains(searchAddr) must always be true.
//
// When added with arenaBaseOffset, we guarantee that
// all valid heap addresses (when also added with
@@ -237,9 +239,15 @@ type pageAlloc struct {
// space on architectures with segmented address spaces.
searchAddr uintptr
- // The address to start a scavenge candidate search with.
+ // The address to start a scavenge candidate search with. It
+ // need not point to memory contained in inUse.
scavAddr uintptr
+ // The amount of memory scavenged since the last scavtrace print.
+ //
+ // Read and updated atomically.
+ scavReleased uintptr
+
// start and end represent the chunk indices
// which pageAlloc knows about. It assumes
// chunks in the range [start, end) are
diff --git a/libgo/go/runtime/mpagealloc_64bit.go b/libgo/go/runtime/mpagealloc_64bit.go
index dd44da1..385b7b3 100644
--- a/libgo/go/runtime/mpagealloc_64bit.go
+++ b/libgo/go/runtime/mpagealloc_64bit.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.
-// +build amd64 !darwin,arm64 mips64 mips64le ppc64 ppc64le s390x arm64be alpha sparc64 ia64 riscv64
+// +build amd64 !darwin,arm64 mips64 mips64le ppc64 ppc64le riscv64 s390x arm64be alpha sparc64 ia64
// See mpagealloc_32bit.go for why darwin/arm64 is excluded here.
diff --git a/libgo/go/runtime/mpagealloc_test.go b/libgo/go/runtime/mpagealloc_test.go
index 6c48296..89a4a25 100644
--- a/libgo/go/runtime/mpagealloc_test.go
+++ b/libgo/go/runtime/mpagealloc_test.go
@@ -41,6 +41,9 @@ func checkPageAlloc(t *testing.T, want, got *PageAlloc) {
}
func TestPageAllocGrow(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
type test struct {
chunks []ChunkIdx
inUse []AddrRange
@@ -216,15 +219,19 @@ func TestPageAllocGrow(t *testing.T) {
}
func TestPageAllocAlloc(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
type hit struct {
npages, base, scav uintptr
}
- tests := map[string]struct {
+ type test struct {
scav map[ChunkIdx][]BitRange
before map[ChunkIdx][]BitRange
after map[ChunkIdx][]BitRange
hits []hit
- }{
+ }
+ tests := map[string]test{
"AllFree1": {
before: map[ChunkIdx][]BitRange{
BaseChunkIdx: {},
@@ -365,7 +372,6 @@ func TestPageAllocAlloc(t *testing.T) {
BaseChunkIdx: {{0, 195}},
},
},
- // TODO(mknyszek): Add tests close to the chunk size.
"ExhaustPallocChunkPages-3": {
before: map[ChunkIdx][]BitRange{
BaseChunkIdx: {},
@@ -565,6 +571,48 @@ func TestPageAllocAlloc(t *testing.T) {
},
},
}
+ if PageAlloc64Bit != 0 {
+ const chunkIdxBigJump = 0x100000 // chunk index offset which translates to O(TiB)
+
+ // This test attempts to trigger a bug wherein we look at unmapped summary
+ // memory that isn't just in the case where we exhaust the heap.
+ //
+ // It achieves this by placing a chunk such that its summary will be
+ // at the very end of a physical page. It then also places another chunk
+ // much further up in the address space, such that any allocations into the
+ // first chunk do not exhaust the heap and the second chunk's summary is not in the
+ // page immediately adjacent to the first chunk's summary's page.
+ // Allocating into this first chunk to exhaustion and then into the second
+ // chunk may then trigger a check in the allocator which erroneously looks at
+ // unmapped summary memory and crashes.
+
+ // Figure out how many chunks are in a physical page, then align BaseChunkIdx
+ // to a physical page in the chunk summary array. Here we only assume that
+ // each summary array is aligned to some physical page.
+ sumsPerPhysPage := ChunkIdx(PhysPageSize / PallocSumBytes)
+ baseChunkIdx := BaseChunkIdx &^ (sumsPerPhysPage - 1)
+ tests["DiscontiguousMappedSumBoundary"] = test{
+ before: map[ChunkIdx][]BitRange{
+ baseChunkIdx + sumsPerPhysPage - 1: {},
+ baseChunkIdx + chunkIdxBigJump: {},
+ },
+ scav: map[ChunkIdx][]BitRange{
+ baseChunkIdx + sumsPerPhysPage - 1: {},
+ baseChunkIdx + chunkIdxBigJump: {},
+ },
+ hits: []hit{
+ {PallocChunkPages - 1, PageBase(baseChunkIdx+sumsPerPhysPage-1, 0), 0},
+ {1, PageBase(baseChunkIdx+sumsPerPhysPage-1, PallocChunkPages-1), 0},
+ {1, PageBase(baseChunkIdx+chunkIdxBigJump, 0), 0},
+ {PallocChunkPages - 1, PageBase(baseChunkIdx+chunkIdxBigJump, 1), 0},
+ {1, 0, 0},
+ },
+ after: map[ChunkIdx][]BitRange{
+ baseChunkIdx + sumsPerPhysPage - 1: {{0, PallocChunkPages}},
+ baseChunkIdx + chunkIdxBigJump: {{0, PallocChunkPages}},
+ },
+ }
+ }
for name, v := range tests {
v := v
t.Run(name, func(t *testing.T) {
@@ -589,6 +637,9 @@ func TestPageAllocAlloc(t *testing.T) {
}
func TestPageAllocExhaust(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
for _, npages := range []uintptr{1, 2, 3, 4, 5, 8, 16, 64, 1024, 1025, 2048, 2049} {
npages := npages
t.Run(fmt.Sprintf("%d", npages), func(t *testing.T) {
@@ -638,6 +689,9 @@ func TestPageAllocExhaust(t *testing.T) {
}
func TestPageAllocFree(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
tests := map[string]struct {
before map[ChunkIdx][]BitRange
after map[ChunkIdx][]BitRange
@@ -867,6 +921,9 @@ func TestPageAllocFree(t *testing.T) {
}
func TestPageAllocAllocAndFree(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
type hit struct {
alloc bool
npages uintptr
diff --git a/libgo/go/runtime/mpagecache_test.go b/libgo/go/runtime/mpagecache_test.go
index 6fdaa04..b8cc0bd 100644
--- a/libgo/go/runtime/mpagecache_test.go
+++ b/libgo/go/runtime/mpagecache_test.go
@@ -180,6 +180,9 @@ func TestPageCacheAlloc(t *testing.T) {
}
func TestPageCacheFlush(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
bits64ToBitRanges := func(bits uint64, base uint) []BitRange {
var ranges []BitRange
start, size := uint(0), uint(0)
@@ -254,6 +257,9 @@ func TestPageCacheFlush(t *testing.T) {
}
func TestPageAllocAllocToCache(t *testing.T) {
+ if GOOS == "openbsd" && testing.Short() {
+ t.Skip("skipping because virtual memory is limited; see #36210")
+ }
tests := map[string]struct {
before map[ChunkIdx][]BitRange
scav map[ChunkIdx][]BitRange
diff --git a/libgo/go/runtime/mpallocbits.go b/libgo/go/runtime/mpallocbits.go
index 9d01ff8..a801134 100644
--- a/libgo/go/runtime/mpallocbits.go
+++ b/libgo/go/runtime/mpallocbits.go
@@ -202,17 +202,11 @@ func (b *pallocBits) summarize() pallocSum {
// If find fails to find any free space, it returns an index of ^uint(0) and
// the new searchIdx should be ignored.
//
-// The returned searchIdx is always the index of the first free page found
-// in this bitmap during the search, except if npages == 1, in which
-// case it will be the index just after the first free page, because the
-// index returned as the first result is assumed to be allocated and so
-// represents a minor optimization for that case.
+// Note that if npages == 1, the two returned values will always be identical.
func (b *pallocBits) find(npages uintptr, searchIdx uint) (uint, uint) {
if npages == 1 {
addr := b.find1(searchIdx)
- // Return a searchIdx of addr + 1 since we assume addr will be
- // allocated.
- return addr, addr + 1
+ return addr, addr
} else if npages <= 64 {
return b.findSmallN(npages, searchIdx)
}
diff --git a/libgo/go/runtime/mranges.go b/libgo/go/runtime/mranges.go
index c14e5c7..b133851 100644
--- a/libgo/go/runtime/mranges.go
+++ b/libgo/go/runtime/mranges.go
@@ -29,6 +29,11 @@ func (a addrRange) size() uintptr {
return a.limit - a.base
}
+// contains returns whether or not the range contains a given address.
+func (a addrRange) contains(addr uintptr) bool {
+ return addr >= a.base && addr < a.limit
+}
+
// subtract takes the addrRange toPrune and cuts out any overlap with
// from, then returns the new range. subtract assumes that a and b
// either don't overlap at all, only overlap on one side, or are equal.
@@ -87,6 +92,15 @@ func (a *addrRanges) findSucc(base uintptr) int {
return len(a.ranges)
}
+// contains returns true if a covers the address addr.
+func (a *addrRanges) contains(addr uintptr) bool {
+ i := a.findSucc(addr)
+ if i == 0 {
+ return false
+ }
+ return a.ranges[i-1].contains(addr)
+}
+
// add inserts a new address range to a.
//
// r must not overlap with any address range in a.
diff --git a/libgo/go/runtime/preempt_nonwindows.go b/libgo/go/runtime/preempt_nonwindows.go
new file mode 100644
index 0000000..3066a152
--- /dev/null
+++ b/libgo/go/runtime/preempt_nonwindows.go
@@ -0,0 +1,13 @@
+// Copyright 2020 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.
+
+// +build !windows
+
+package runtime
+
+//go:nosplit
+func osPreemptExtEnter(mp *m) {}
+
+//go:nosplit
+func osPreemptExtExit(mp *m) {}
diff --git a/libgo/go/runtime/proc.go b/libgo/go/runtime/proc.go
index e3f934a..f75cacf 100644
--- a/libgo/go/runtime/proc.go
+++ b/libgo/go/runtime/proc.go
@@ -841,23 +841,8 @@ func casGFromPreempted(gp *g, old, new uint32) bool {
// goroutines.
func stopTheWorld(reason string) {
semacquire(&worldsema)
- gp := getg()
- gp.m.preemptoff = reason
- systemstack(func() {
- // Mark the goroutine which called stopTheWorld preemptible so its
- // stack may be scanned.
- // This lets a mark worker scan us while we try to stop the world
- // since otherwise we could get in a mutual preemption deadlock.
- // We must not modify anything on the G stack because a stack shrink
- // may occur. A stack shrink is otherwise OK though because in order
- // to return from this function (and to leave the system stack) we
- // must have preempted all goroutines, including any attempting
- // to scan our stack, in which case, any stack shrinking will
- // have already completed by the time we exit.
- casgstatus(gp, _Grunning, _Gwaiting)
- stopTheWorldWithSema()
- casgstatus(gp, _Gwaiting, _Grunning)
- })
+ getg().m.preemptoff = reason
+ systemstack(stopTheWorldWithSema)
}
// startTheWorld undoes the effects of stopTheWorld.
@@ -869,31 +854,10 @@ func startTheWorld() {
getg().m.preemptoff = ""
}
-// stopTheWorldGC has the same effect as stopTheWorld, but blocks
-// until the GC is not running. It also blocks a GC from starting
-// until startTheWorldGC is called.
-func stopTheWorldGC(reason string) {
- semacquire(&gcsema)
- stopTheWorld(reason)
-}
-
-// startTheWorldGC undoes the effects of stopTheWorldGC.
-func startTheWorldGC() {
- startTheWorld()
- semrelease(&gcsema)
-}
-
-// Holding worldsema grants an M the right to try to stop the world.
+// Holding worldsema grants an M the right to try to stop the world
+// and prevents gomaxprocs from changing concurrently.
var worldsema uint32 = 1
-// Holding gcsema grants the M the right to block a GC, and blocks
-// until the current GC is done. In particular, it prevents gomaxprocs
-// from changing concurrently.
-//
-// TODO(mknyszek): Once gomaxprocs and the execution tracer can handle
-// being changed/enabled during a GC, remove this.
-var gcsema uint32 = 1
-
// stopTheWorldWithSema is the core implementation of stopTheWorld.
// The caller is responsible for acquiring worldsema and disabling
// preemption first and then should stopTheWorldWithSema on the system
@@ -2577,6 +2541,27 @@ func dropg() {
// We pass now in and out to avoid extra calls of nanotime.
//go:yeswritebarrierrec
func checkTimers(pp *p, now int64) (rnow, pollUntil int64, ran bool) {
+ // If there are no timers to adjust, and the first timer on
+ // the heap is not yet ready to run, then there is nothing to do.
+ if atomic.Load(&pp.adjustTimers) == 0 {
+ next := int64(atomic.Load64(&pp.timer0When))
+ if next == 0 {
+ return now, 0, false
+ }
+ if now == 0 {
+ now = nanotime()
+ }
+ if now < next {
+ // Next timer is not ready to run.
+ // But keep going if we would clear deleted timers.
+ // This corresponds to the condition below where
+ // we decide whether to call clearDeletedTimers.
+ if pp != getg().m.p.ptr() || int(atomic.Load(&pp.deletedTimers)) <= int(atomic.Load(&pp.numTimers)/4) {
+ return now, next, false
+ }
+ }
+ }
+
lock(&pp.timersLock)
adjusttimers(pp)
@@ -2599,6 +2584,13 @@ func checkTimers(pp *p, now int64) (rnow, pollUntil int64, ran bool) {
}
}
+ // If this is the local P, and there are a lot of deleted timers,
+ // clear them out. We only do this for the local P to reduce
+ // lock contention on timersLock.
+ if pp == getg().m.p.ptr() && int(atomic.Load(&pp.deletedTimers)) > len(pp.timers)/4 {
+ clearDeletedTimers(pp)
+ }
+
unlock(&pp.timersLock)
return rnow, pollUntil, ran
@@ -2723,7 +2715,7 @@ func preemptPark(gp *g) {
}
// goyield is like Gosched, but it:
-// - does not emit a GoSched trace event
+// - emits a GoPreempt trace event instead of a GoSched trace event
// - puts the current G on the runq of the current P instead of the globrunq
func goyield() {
checkTimeouts()
@@ -2731,6 +2723,9 @@ func goyield() {
}
func goyield_m(gp *g) {
+ if trace.enabled {
+ traceGoPreempt()
+ }
pp := gp.m.p.ptr()
casgstatus(gp, _Grunning, _Grunnable)
dropg()
@@ -3816,7 +3811,10 @@ func (pp *p) destroy() {
lock(&pp.timersLock)
moveTimers(plocal, pp.timers)
pp.timers = nil
+ pp.numTimers = 0
pp.adjustTimers = 0
+ pp.deletedTimers = 0
+ atomic.Store64(&pp.timer0When, 0)
unlock(&pp.timersLock)
unlock(&plocal.timersLock)
}
@@ -4122,23 +4120,26 @@ func checkdead() {
}
// Maybe jump time forward for playground.
- _p_ := timejump()
- if _p_ != nil {
- for pp := &sched.pidle; *pp != 0; pp = &(*pp).ptr().link {
- if (*pp).ptr() == _p_ {
- *pp = _p_.link
- break
+ if faketime != 0 {
+ when, _p_ := timeSleepUntil()
+ if _p_ != nil {
+ faketime = when
+ for pp := &sched.pidle; *pp != 0; pp = &(*pp).ptr().link {
+ if (*pp).ptr() == _p_ {
+ *pp = _p_.link
+ break
+ }
}
+ mp := mget()
+ if mp == nil {
+ // There should always be a free M since
+ // nothing is running.
+ throw("checkdead: no m for timer")
+ }
+ mp.nextp.set(_p_)
+ notewakeup(&mp.park)
+ return
}
- mp := mget()
- if mp == nil {
- // There should always be a free M since
- // nothing is running.
- throw("checkdead: no m for timer")
- }
- mp.nextp.set(_p_)
- notewakeup(&mp.park)
- return
}
// There are no goroutines running, so we can look at the P's.
@@ -4183,7 +4184,7 @@ func sysmon() {
}
usleep(delay)
now := nanotime()
- next := timeSleepUntil()
+ next, _ := timeSleepUntil()
if debug.schedtrace <= 0 && (sched.gcwaiting != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs)) {
lock(&sched.lock)
if atomic.Load(&sched.gcwaiting) != 0 || atomic.Load(&sched.npidle) == uint32(gomaxprocs) {
@@ -4205,7 +4206,7 @@ func sysmon() {
osRelax(false)
}
now = nanotime()
- next = timeSleepUntil()
+ next, _ = timeSleepUntil()
lock(&sched.lock)
atomic.Store(&sched.sysmonwait, 0)
noteclear(&sched.sysmonnote)
diff --git a/libgo/go/runtime/runtime1.go b/libgo/go/runtime/runtime1.go
index 60aa90f..6edf7a5 100644
--- a/libgo/go/runtime/runtime1.go
+++ b/libgo/go/runtime/runtime1.go
@@ -323,6 +323,7 @@ var debug struct {
madvdontneed int32 // for Linux; issue 28466
sbrk int32
scavenge int32
+ scavtrace int32
scheddetail int32
schedtrace int32
tracebackancestors int32
@@ -343,6 +344,7 @@ var dbgvars = []dbgVar{
{"madvdontneed", &debug.madvdontneed},
{"sbrk", &debug.sbrk},
{"scavenge", &debug.scavenge},
+ {"scavtrace", &debug.scavtrace},
{"scheddetail", &debug.scheddetail},
{"schedtrace", &debug.schedtrace},
{"tracebackancestors", &debug.tracebackancestors},
diff --git a/libgo/go/runtime/runtime2.go b/libgo/go/runtime/runtime2.go
index d50f82a..f5bfc08 100644
--- a/libgo/go/runtime/runtime2.go
+++ b/libgo/go/runtime/runtime2.go
@@ -677,6 +677,11 @@ type p struct {
_ uint32 // Alignment for atomic fields below
+ // The when field of the first entry on the timer heap.
+ // This is updated using atomic functions.
+ // This is 0 if the timer heap is empty.
+ timer0When uint64
+
// Per-P GC state
gcAssistTime int64 // Nanoseconds in assistAlloc
gcFractionalMarkTime int64 // Nanoseconds in fractional mark worker (atomic)
@@ -708,12 +713,20 @@ type p struct {
// Must hold timersLock to access.
timers []*timer
+ // Number of timers in P's heap.
+ // Modified using atomic instructions.
+ numTimers uint32
+
// Number of timerModifiedEarlier timers on P's heap.
// This should only be modified while holding timersLock,
// or while the timer status is in a transient state
// such as timerModifying.
adjustTimers uint32
+ // Number of timerDeleted timers in P's heap.
+ // Modified using atomic instructions.
+ deletedTimers uint32
+
// Race context used while executing timer functions.
// Not for gccgo: timerRaceCtx uintptr
diff --git a/libgo/go/runtime/sema.go b/libgo/go/runtime/sema.go
index fb16796..b6fab6d 100644
--- a/libgo/go/runtime/sema.go
+++ b/libgo/go/runtime/sema.go
@@ -199,9 +199,9 @@ func semrelease1(addr *uint32, handoff bool, skipframes int) {
// the waiter G immediately.
// Note that waiter inherits our time slice: this is desirable
// to avoid having a highly contended semaphore hog the P
- // indefinitely. goyield is like Gosched, but it does not emit a
- // GoSched trace event and, more importantly, puts the current G
- // on the local runq instead of the global one.
+ // indefinitely. goyield is like Gosched, but it emits a
+ // "preempted" trace event instead and, more importantly, puts
+ // the current G on the local runq instead of the global one.
// We only do this in the starving regime (handoff=true), as in
// the non-starving case it is possible for a different waiter
// to acquire the semaphore while we are yielding/scheduling,
diff --git a/libgo/go/runtime/signal_unix.go b/libgo/go/runtime/signal_unix.go
index 29f9443..150345f 100644
--- a/libgo/go/runtime/signal_unix.go
+++ b/libgo/go/runtime/signal_unix.go
@@ -399,6 +399,16 @@ func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) {
sigprofNonGo(pc)
return
}
+ if sig == sigPreempt && preemptMSupported && debug.asyncpreemptoff == 0 {
+ // This is probably a signal from preemptM sent
+ // while executing Go code but received while
+ // executing non-Go code.
+ // We got past sigfwdgo, so we know that there is
+ // no non-Go signal handler for sigPreempt.
+ // The default behavior for sigPreempt is to ignore
+ // the signal, so badsignal will be a no-op anyway.
+ return
+ }
badsignal(uintptr(sig), &c)
return
}
diff --git a/libgo/go/runtime/testdata/testprog/checkptr.go b/libgo/go/runtime/testdata/testprog/checkptr.go
new file mode 100644
index 0000000..177db38
--- /dev/null
+++ b/libgo/go/runtime/testdata/testprog/checkptr.go
@@ -0,0 +1,36 @@
+// Copyright 2020 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 "unsafe"
+
+func init() {
+ register("CheckPtrAlignment", CheckPtrAlignment)
+ register("CheckPtrArithmetic", CheckPtrArithmetic)
+ register("CheckPtrSize", CheckPtrSize)
+ register("CheckPtrSmall", CheckPtrSmall)
+}
+
+func CheckPtrAlignment() {
+ var x [2]int64
+ p := unsafe.Pointer(&x[0])
+ sink2 = (*int64)(unsafe.Pointer(uintptr(p) + 1))
+}
+
+func CheckPtrArithmetic() {
+ var x int
+ i := uintptr(unsafe.Pointer(&x))
+ sink2 = (*int)(unsafe.Pointer(i))
+}
+
+func CheckPtrSize() {
+ p := new(int64)
+ sink2 = p
+ sink2 = (*[100]int64)(unsafe.Pointer(p))
+}
+
+func CheckPtrSmall() {
+ sink2 = unsafe.Pointer(uintptr(1))
+}
diff --git a/libgo/go/runtime/time.go b/libgo/go/runtime/time.go
index ded68ed..d0dd3a4 100644
--- a/libgo/go/runtime/time.go
+++ b/libgo/go/runtime/time.go
@@ -73,14 +73,15 @@ type timer struct {
// timerNoStatus -> timerWaiting
// anything else -> panic: invalid value
// deltimer:
-// timerWaiting -> timerDeleted
-// timerModifiedXX -> timerDeleted
-// timerNoStatus -> do nothing
-// timerDeleted -> do nothing
-// timerRemoving -> do nothing
-// timerRemoved -> do nothing
-// timerRunning -> wait until status changes
-// timerMoving -> wait until status changes
+// timerWaiting -> timerDeleted
+// timerModifiedEarlier -> timerModifying -> timerDeleted
+// timerModifiedLater -> timerDeleted
+// timerNoStatus -> do nothing
+// timerDeleted -> do nothing
+// timerRemoving -> do nothing
+// timerRemoved -> do nothing
+// timerRunning -> wait until status changes
+// timerMoving -> wait until status changes
// timerModifying -> panic: concurrent deltimer/modtimer calls
// modtimer:
// timerWaiting -> timerModifying -> timerModifiedXX
@@ -168,6 +169,10 @@ const (
// maxWhen is the maximum value for timer's when field.
const maxWhen = 1<<63 - 1
+// verifyTimers can be set to true to add debugging checks that the
+// timer heaps are valid.
+const verifyTimers = false
+
// Package time APIs.
// Godoc uses the comments in package time, not these.
@@ -283,7 +288,12 @@ func doaddtimer(pp *p, t *timer) bool {
t.pp.set(pp)
i := len(pp.timers)
pp.timers = append(pp.timers, t)
- return siftupTimer(pp.timers, i)
+ ok := siftupTimer(pp.timers, i)
+ if t == pp.timers[0] {
+ atomic.Store64(&pp.timer0When, uint64(t.when))
+ }
+ atomic.Xadd(&pp.numTimers, 1)
+ return ok
}
// deltimer deletes the timer t. It may be on some other P, so we can't
@@ -294,7 +304,9 @@ func deltimer(t *timer) bool {
for {
switch s := atomic.Load(&t.status); s {
case timerWaiting, timerModifiedLater:
+ tpp := t.pp.ptr()
if atomic.Cas(&t.status, s, timerDeleted) {
+ atomic.Xadd(&tpp.deletedTimers, 1)
// Timer was not yet run.
return true
}
@@ -305,6 +317,7 @@ func deltimer(t *timer) bool {
if !atomic.Cas(&t.status, timerModifying, timerDeleted) {
badTimer()
}
+ atomic.Xadd(&tpp.deletedTimers, 1)
// Timer was not yet run.
return true
}
@@ -355,6 +368,10 @@ func dodeltimer(pp *p, i int) bool {
ok = false
}
}
+ if i == 0 {
+ updateTimer0When(pp)
+ }
+ atomic.Xadd(&pp.numTimers, -1)
return ok
}
@@ -378,6 +395,8 @@ func dodeltimer0(pp *p) bool {
if last > 0 {
ok = siftdownTimer(pp.timers, 0)
}
+ updateTimer0When(pp)
+ atomic.Xadd(&pp.numTimers, -1)
return ok
}
@@ -485,6 +504,7 @@ func resettimer(t *timer, when int64) {
return
}
case timerDeleted:
+ tpp := t.pp.ptr()
if atomic.Cas(&t.status, s, timerModifying) {
t.nextwhen = when
newStatus := uint32(timerModifiedLater)
@@ -495,6 +515,7 @@ func resettimer(t *timer, when int64) {
if !atomic.Cas(&t.status, timerModifying, newStatus) {
badTimer()
}
+ atomic.Xadd(&tpp.deletedTimers, -1)
if newStatus == timerModifiedEarlier {
wakeNetPoller(when)
}
@@ -542,6 +563,7 @@ func cleantimers(pp *p) bool {
if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
return false
}
+ atomic.Xadd(&pp.deletedTimers, -1)
case timerModifiedEarlier, timerModifiedLater:
if !atomic.Cas(&t.status, s, timerMoving) {
continue
@@ -630,9 +652,13 @@ func adjusttimers(pp *p) {
return
}
if atomic.Load(&pp.adjustTimers) == 0 {
+ if verifyTimers {
+ verifyTimerHeap(pp)
+ }
return
}
var moved []*timer
+loop:
for i := 0; i < len(pp.timers); i++ {
t := pp.timers[i]
if t.pp.ptr() != pp {
@@ -647,6 +673,7 @@ func adjusttimers(pp *p) {
if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
badTimer()
}
+ atomic.Xadd(&pp.deletedTimers, -1)
// Look at this heap position again.
i--
}
@@ -664,10 +691,11 @@ func adjusttimers(pp *p) {
moved = append(moved, t)
if s == timerModifiedEarlier {
if n := atomic.Xadd(&pp.adjustTimers, -1); int32(n) <= 0 {
- addAdjustedTimers(pp, moved)
- return
+ break loop
}
}
+ // Look at this heap position again.
+ i--
}
case timerNoStatus, timerRunning, timerRemoving, timerRemoved, timerMoving:
badTimer()
@@ -685,6 +713,10 @@ func adjusttimers(pp *p) {
if len(moved) > 0 {
addAdjustedTimers(pp, moved)
}
+
+ if verifyTimers {
+ verifyTimerHeap(pp)
+ }
}
// addAdjustedTimers adds any timers we adjusted in adjusttimers
@@ -708,17 +740,11 @@ func addAdjustedTimers(pp *p, moved []*timer) {
// The netpoller M will wake up and adjust timers before sleeping again.
//go:nowritebarrierrec
func nobarrierWakeTime(pp *p) int64 {
- lock(&pp.timersLock)
- ret := int64(0)
- if len(pp.timers) > 0 {
- if atomic.Load(&pp.adjustTimers) > 0 {
- ret = nanotime()
- } else {
- ret = pp.timers[0].when
- }
+ if atomic.Load(&pp.adjustTimers) > 0 {
+ return nanotime()
+ } else {
+ return int64(atomic.Load64(&pp.timer0When))
}
- unlock(&pp.timersLock)
- return ret
}
// runtimer examines the first timer in timers. If it is ready based on now,
@@ -759,6 +785,7 @@ func runtimer(pp *p, now int64) int64 {
if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
badTimer()
}
+ atomic.Xadd(&pp.deletedTimers, -1)
if len(pp.timers) == 0 {
return -1
}
@@ -817,6 +844,7 @@ func runOneTimer(pp *p, t *timer, now int64) {
if !atomic.Cas(&t.status, timerRunning, timerWaiting) {
badTimer()
}
+ updateTimer0When(pp)
} else {
// Remove from heap.
if !dodeltimer0(pp) {
@@ -834,69 +862,131 @@ func runOneTimer(pp *p, t *timer, now int64) {
lock(&pp.timersLock)
}
-func timejump() *p {
- if faketime == 0 {
- return nil
- }
-
- // Nothing is running, so we can look at all the P's.
- // Determine a timer bucket with minimum when.
- var (
- minT *timer
- minWhen int64
- minP *p
- )
- for _, pp := range allp {
- if pp.status != _Pidle && pp.status != _Pdead {
- throw("non-idle P in timejump")
- }
- if len(pp.timers) == 0 {
- continue
- }
- c := pp.adjustTimers
- for _, t := range pp.timers {
+// clearDeletedTimers removes all deleted timers from the P's timer heap.
+// This is used to avoid clogging up the heap if the program
+// starts a lot of long-running timers and then stops them.
+// For example, this can happen via context.WithTimeout.
+//
+// This is the only function that walks through the entire timer heap,
+// other than moveTimers which only runs when the world is stopped.
+//
+// The caller must have locked the timers for pp.
+func clearDeletedTimers(pp *p) {
+ cdel := int32(0)
+ cearlier := int32(0)
+ to := 0
+ changedHeap := false
+ timers := pp.timers
+nextTimer:
+ for _, t := range timers {
+ for {
switch s := atomic.Load(&t.status); s {
case timerWaiting:
- if minT == nil || t.when < minWhen {
- minT = t
- minWhen = t.when
- minP = pp
+ if changedHeap {
+ timers[to] = t
+ siftupTimer(timers, to)
}
+ to++
+ continue nextTimer
case timerModifiedEarlier, timerModifiedLater:
- if minT == nil || t.nextwhen < minWhen {
- minT = t
- minWhen = t.nextwhen
- minP = pp
+ if atomic.Cas(&t.status, s, timerMoving) {
+ t.when = t.nextwhen
+ timers[to] = t
+ siftupTimer(timers, to)
+ to++
+ changedHeap = true
+ if !atomic.Cas(&t.status, timerMoving, timerWaiting) {
+ badTimer()
+ }
+ if s == timerModifiedEarlier {
+ cearlier++
+ }
+ continue nextTimer
}
- if s == timerModifiedEarlier {
- c--
+ case timerDeleted:
+ if atomic.Cas(&t.status, s, timerRemoving) {
+ t.pp = 0
+ cdel++
+ if !atomic.Cas(&t.status, timerRemoving, timerRemoved) {
+ badTimer()
+ }
+ changedHeap = true
+ continue nextTimer
}
- case timerRunning, timerModifying, timerMoving:
+ case timerModifying:
+ // Loop until modification complete.
+ osyield()
+ case timerNoStatus, timerRemoved:
+ // We should not see these status values in a timer heap.
+ badTimer()
+ case timerRunning, timerRemoving, timerMoving:
+ // Some other P thinks it owns this timer,
+ // which should not happen.
+ badTimer()
+ default:
badTimer()
- }
- // The timers are sorted, so we only have to check
- // the first timer for each P, unless there are
- // some timerModifiedEarlier timers. The number
- // of timerModifiedEarlier timers is in the adjustTimers
- // field, used to initialize c, above.
- if c == 0 {
- break
}
}
}
- if minT == nil || minWhen <= faketime {
- return nil
+ // Set remaining slots in timers slice to nil,
+ // so that the timer values can be garbage collected.
+ for i := to; i < len(timers); i++ {
+ timers[i] = nil
+ }
+
+ atomic.Xadd(&pp.deletedTimers, -cdel)
+ atomic.Xadd(&pp.numTimers, -cdel)
+ atomic.Xadd(&pp.adjustTimers, -cearlier)
+
+ timers = timers[:to]
+ pp.timers = timers
+ updateTimer0When(pp)
+
+ if verifyTimers {
+ verifyTimerHeap(pp)
+ }
+}
+
+// verifyTimerHeap verifies that the timer heap is in a valid state.
+// This is only for debugging, and is only called if verifyTimers is true.
+// The caller must have locked the timers.
+func verifyTimerHeap(pp *p) {
+ for i, t := range pp.timers {
+ if i == 0 {
+ // First timer has no parent.
+ continue
+ }
+
+ // The heap is 4-ary. See siftupTimer and siftdownTimer.
+ p := (i - 1) / 4
+ if t.when < pp.timers[p].when {
+ print("bad timer heap at ", i, ": ", p, ": ", pp.timers[p].when, ", ", i, ": ", t.when, "\n")
+ throw("bad timer heap")
+ }
+ }
+ if numTimers := int(atomic.Load(&pp.numTimers)); len(pp.timers) != numTimers {
+ println("timer heap len", len(pp.timers), "!= numTimers", numTimers)
+ throw("bad timer heap len")
}
+}
- faketime = minWhen
- return minP
+// updateTimer0When sets the P's timer0When field.
+// The caller must have locked the timers for pp.
+func updateTimer0When(pp *p) {
+ if len(pp.timers) == 0 {
+ atomic.Store64(&pp.timer0When, 0)
+ } else {
+ atomic.Store64(&pp.timer0When, uint64(pp.timers[0].when))
+ }
}
-// timeSleepUntil returns the time when the next timer should fire.
-// This is only called by sysmon.
-func timeSleepUntil() int64 {
+// timeSleepUntil returns the time when the next timer should fire,
+// and the P that holds the timer heap that that timer is on.
+// This is only called by sysmon and checkdead.
+func timeSleepUntil() (int64, *p) {
next := int64(maxWhen)
+ var pret *p
// Prevent allp slice changes. This is like retake.
lock(&allpLock)
@@ -907,8 +997,17 @@ func timeSleepUntil() int64 {
continue
}
- lock(&pp.timersLock)
c := atomic.Load(&pp.adjustTimers)
+ if c == 0 {
+ w := int64(atomic.Load64(&pp.timer0When))
+ if w != 0 && w < next {
+ next = w
+ pret = pp
+ }
+ continue
+ }
+
+ lock(&pp.timersLock)
for _, t := range pp.timers {
switch s := atomic.Load(&t.status); s {
case timerWaiting:
@@ -943,7 +1042,7 @@ func timeSleepUntil() int64 {
}
unlock(&allpLock)
- return next
+ return next, pret
}
// Heap maintenance algorithms.
diff --git a/libgo/go/runtime/trace.go b/libgo/go/runtime/trace.go
index 81ff0ca..358674b 100644
--- a/libgo/go/runtime/trace.go
+++ b/libgo/go/runtime/trace.go
@@ -181,12 +181,9 @@ func traceBufPtrOf(b *traceBuf) traceBufPtr {
// Most clients should use the runtime/trace package or the testing package's
// -test.trace flag instead of calling StartTrace directly.
func StartTrace() error {
- // Stop the world so that we can take a consistent snapshot
+ // Stop the world, so that we can take a consistent snapshot
// of all goroutines at the beginning of the trace.
- // Do not stop the world during GC so we ensure we always see
- // a consistent view of GC-related events (e.g. a start is always
- // paired with an end).
- stopTheWorldGC("start tracing")
+ stopTheWorld("start tracing")
// We are in stop-the-world, but syscalls can finish and write to trace concurrently.
// Exitsyscall could check trace.enabled long before and then suddenly wake up
@@ -197,7 +194,7 @@ func StartTrace() error {
if trace.enabled || trace.shutdown {
unlock(&trace.bufLock)
- startTheWorldGC()
+ startTheWorld()
return errorString("tracing is already enabled")
}
@@ -268,7 +265,7 @@ func StartTrace() error {
unlock(&trace.bufLock)
- startTheWorldGC()
+ startTheWorld()
return nil
}
@@ -277,14 +274,14 @@ func StartTrace() error {
func StopTrace() {
// Stop the world so that we can collect the trace buffers from all p's below,
// and also to avoid races with traceEvent.
- stopTheWorldGC("stop tracing")
+ stopTheWorld("stop tracing")
// See the comment in StartTrace.
lock(&trace.bufLock)
if !trace.enabled {
unlock(&trace.bufLock)
- startTheWorldGC()
+ startTheWorld()
return
}
@@ -321,7 +318,7 @@ func StopTrace() {
trace.shutdown = true
unlock(&trace.bufLock)
- startTheWorldGC()
+ startTheWorld()
// The world is started but we've set trace.shutdown, so new tracing can't start.
// Wait for the trace reader to flush pending buffers and stop.
diff --git a/libgo/go/runtime/trace/trace_stack_test.go b/libgo/go/runtime/trace/trace_stack_test.go
index e3608c6..62c06e6 100644
--- a/libgo/go/runtime/trace/trace_stack_test.go
+++ b/libgo/go/runtime/trace/trace_stack_test.go
@@ -233,7 +233,6 @@ func TestTraceSymbolize(t *testing.T) {
}},
{trace.EvGomaxprocs, []frame{
{"runtime.startTheWorld", 0}, // this is when the current gomaxprocs is logged.
- {"runtime.startTheWorldGC", 0},
{"runtime.GOMAXPROCS", 0},
{"runtime/trace_test.TestTraceSymbolize", 0},
{"testing.tRunner", 0},
diff --git a/libgo/go/runtime/utf8.go b/libgo/go/runtime/utf8.go
index 6590472..a404a33 100644
--- a/libgo/go/runtime/utf8.go
+++ b/libgo/go/runtime/utf8.go
@@ -13,7 +13,7 @@ import _ "unsafe" // For go:linkname.
// Numbers fundamental to the encoding.
const (
runeError = '\uFFFD' // the "error" Rune or "Unicode replacement character"
- runeSelf = 0x80 // characters below Runeself are represented as themselves in a single byte.
+ runeSelf = 0x80 // characters below runeSelf are represented as themselves in a single byte.
maxRune = '\U0010FFFF' // Maximum valid Unicode code point.
)
diff --git a/libgo/go/strconv/quote.go b/libgo/go/strconv/quote.go
index b50496a..bcbdbc5 100644
--- a/libgo/go/strconv/quote.go
+++ b/libgo/go/strconv/quote.go
@@ -145,8 +145,9 @@ func AppendQuoteToASCII(dst []byte, s string) []byte {
}
// QuoteToGraphic returns a double-quoted Go string literal representing s.
-// The returned string uses Go escape sequences (\t, \n, \xFF, \u0100) for
-// non-ASCII characters and non-printable characters as defined by IsGraphic.
+// The returned string leaves Unicode graphic characters, as defined by
+// IsGraphic, unchanged and uses Go escape sequences (\t, \n, \xFF, \u0100)
+// for non-graphic characters.
func QuoteToGraphic(s string) string {
return quoteWith(s, '"', false, true)
}
@@ -185,9 +186,9 @@ func AppendQuoteRuneToASCII(dst []byte, r rune) []byte {
}
// QuoteRuneToGraphic returns a single-quoted Go character literal representing
-// the rune. The returned string uses Go escape sequences (\t, \n, \xFF,
-// \u0100) for non-ASCII characters and non-printable characters as defined
-// by IsGraphic.
+// the rune. If the rune is not a Unicode graphic character,
+// as defined by IsGraphic, the returned string will use a Go escape sequence
+// (\t, \n, \xFF, \u0100).
func QuoteRuneToGraphic(r rune) string {
return quoteRuneWith(r, '\'', false, true)
}
diff --git a/libgo/go/strings/strings.go b/libgo/go/strings/strings.go
index 69f51b6..238d657 100644
--- a/libgo/go/strings/strings.go
+++ b/libgo/go/strings/strings.go
@@ -420,24 +420,24 @@ func FieldsFunc(s string, f func(rune) bool) []string {
return a
}
-// Join concatenates the elements of a to create a single string. The separator string
-// sep is placed between elements in the resulting string.
-func Join(a []string, sep string) string {
- switch len(a) {
+// Join concatenates the elements of its first argument to create a single string. The separator
+// string sep is placed between elements in the resulting string.
+func Join(elems []string, sep string) string {
+ switch len(elems) {
case 0:
return ""
case 1:
- return a[0]
+ return elems[0]
}
- n := len(sep) * (len(a) - 1)
- for i := 0; i < len(a); i++ {
- n += len(a[i])
+ n := len(sep) * (len(elems) - 1)
+ for i := 0; i < len(elems); i++ {
+ n += len(elems[i])
}
var b Builder
b.Grow(n)
- b.WriteString(a[0])
- for _, s := range a[1:] {
+ b.WriteString(elems[0])
+ for _, s := range elems[1:] {
b.WriteString(sep)
b.WriteString(s)
}
diff --git a/libgo/go/syscall/syscall_aix.go b/libgo/go/syscall/syscall_aix.go
index f4cac01..af0b883 100644
--- a/libgo/go/syscall/syscall_aix.go
+++ b/libgo/go/syscall/syscall_aix.go
@@ -4,7 +4,9 @@
package syscall
-import "unsafe"
+import (
+ "unsafe"
+)
func (ts *StTimespec) Unix() (sec int64, nsec int64) {
return int64(ts.Sec), int64(ts.Nsec)
diff --git a/libgo/go/testing/benchmark.go b/libgo/go/testing/benchmark.go
index 0412772..93f461b 100644
--- a/libgo/go/testing/benchmark.go
+++ b/libgo/go/testing/benchmark.go
@@ -86,7 +86,7 @@ type InternalBenchmark struct {
// may be called simultaneously from multiple goroutines.
//
// Like in tests, benchmark logs are accumulated during execution
-// and dumped to standard error when done. Unlike in tests, benchmark logs
+// and dumped to standard output when done. Unlike in tests, benchmark logs
// are always printed, so as not to hide output whose existence may be
// affecting benchmark results.
type B struct {
diff --git a/libgo/go/testing/panic_test.go b/libgo/go/testing/panic_test.go
index 3491510..6b8b953 100644
--- a/libgo/go/testing/panic_test.go
+++ b/libgo/go/testing/panic_test.go
@@ -16,6 +16,9 @@ import (
)
var testPanicTest = flag.String("test_panic_test", "", "TestPanic: indicates which test should panic")
+var testPanicParallel = flag.Bool("test_panic_parallel", false, "TestPanic: run subtests in parallel")
+var testPanicCleanup = flag.Bool("test_panic_cleanup", false, "TestPanic: indicates whether test should call Cleanup")
+var testPanicCleanupPanic = flag.String("test_panic_cleanup_panic", "", "TestPanic: indicate whether test should call Cleanup function that panics")
func TestPanic(t *testing.T) {
testenv.MustHaveExec(t)
@@ -40,6 +43,98 @@ func TestPanic(t *testing.T) {
--- FAIL: TestPanicHelper/1 (N.NNs)
panic_test.go:NNN: TestPanicHelper/1
`,
+ }, {
+ desc: "subtest panics with cleanup",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "subtest panics with outer cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+`,
+ }, {
+ desc: "subtest panics with middle cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "subtest panics with inner cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "parallel subtest panics with cleanup",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "parallel subtest panics with outer cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=outer", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+`,
+ }, {
+ desc: "parallel subtest panics with middle cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=middle", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
+ }, {
+ desc: "parallel subtest panics with inner cleanup panic",
+ flags: []string{"-test_panic_test=TestPanicHelper/1", "-test_panic_cleanup", "-test_panic_cleanup_panic=inner", "-test_panic_parallel"},
+ want: `
+ran inner cleanup 1
+ran middle cleanup 1
+ran outer cleanup
+--- FAIL: TestPanicHelper (N.NNs)
+ panic_test.go:NNN: TestPanicHelper
+ --- FAIL: TestPanicHelper/1 (N.NNs)
+ panic_test.go:NNN: TestPanicHelper/1
+`,
}}
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
@@ -72,10 +167,42 @@ func TestPanicHelper(t *testing.T) {
if t.Name() == *testPanicTest {
panic("panic")
}
+ switch *testPanicCleanupPanic {
+ case "", "outer", "middle", "inner":
+ default:
+ t.Fatalf("bad -test_panic_cleanup_panic: %s", *testPanicCleanupPanic)
+ }
+ t.Cleanup(func() {
+ fmt.Println("ran outer cleanup")
+ if *testPanicCleanupPanic == "outer" {
+ panic("outer cleanup")
+ }
+ })
for i := 0; i < 3; i++ {
+ i := i
t.Run(fmt.Sprintf("%v", i), func(t *testing.T) {
+ chosen := t.Name() == *testPanicTest
+ if chosen && *testPanicCleanup {
+ t.Cleanup(func() {
+ fmt.Printf("ran middle cleanup %d\n", i)
+ if *testPanicCleanupPanic == "middle" {
+ panic("middle cleanup")
+ }
+ })
+ }
+ if chosen && *testPanicParallel {
+ t.Parallel()
+ }
t.Log(t.Name())
- if t.Name() == *testPanicTest {
+ if chosen {
+ if *testPanicCleanup {
+ t.Cleanup(func() {
+ fmt.Printf("ran inner cleanup %d\n", i)
+ if *testPanicCleanupPanic == "inner" {
+ panic("inner cleanup")
+ }
+ })
+ }
panic("panic")
}
})
diff --git a/libgo/go/testing/sub_test.go b/libgo/go/testing/sub_test.go
index 3f0f71f..3dc30ee 100644
--- a/libgo/go/testing/sub_test.go
+++ b/libgo/go/testing/sub_test.go
@@ -460,6 +460,21 @@ func TestTRun(t *T) {
<-ch
t.Errorf("error")
},
+ }, {
+ // If a subtest panics we should run cleanups.
+ desc: "cleanup when subtest panics",
+ ok: false,
+ chatty: false,
+ output: `
+--- FAIL: cleanup when subtest panics (N.NNs)
+ --- FAIL: cleanup when subtest panics/sub (N.NNs)
+ sub_test.go:NNN: running cleanup`,
+ f: func(t *T) {
+ t.Cleanup(func() { t.Log("running cleanup") })
+ t.Run("sub", func(t2 *T) {
+ t2.FailNow()
+ })
+ },
}}
for _, tc := range testCases {
ctx := newTestContext(tc.maxPar, newMatcher(regexp.MatchString, "", ""))
@@ -855,3 +870,19 @@ func TestRunCleanup(t *T) {
t.Errorf("unexpected outer cleanup count; got %d want 0", outerCleanup)
}
}
+
+func TestCleanupParallelSubtests(t *T) {
+ ranCleanup := 0
+ t.Run("test", func(t *T) {
+ t.Cleanup(func() { ranCleanup++ })
+ t.Run("x", func(t *T) {
+ t.Parallel()
+ if ranCleanup > 0 {
+ t.Error("outer cleanup ran before parallel subtest")
+ }
+ })
+ })
+ if ranCleanup != 1 {
+ t.Errorf("unexpected cleanup count; got %d want 1", ranCleanup)
+ }
+}
diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go
index e05314e..67892d7 100644
--- a/libgo/go/testing/testing.go
+++ b/libgo/go/testing/testing.go
@@ -812,9 +812,9 @@ func (c *common) Helper() {
c.helpers[callerName(1)] = struct{}{}
}
-// Cleanup registers a function to be called when the test finishes.
-// Cleanup functions will be called in last added, first called
-// order.
+// Cleanup registers a function to be called when the test and all its
+// subtests complete. Cleanup functions will be called in last added,
+// first called order.
func (c *common) Cleanup(f func()) {
c.mu.Lock()
defer c.mu.Unlock()
@@ -827,15 +827,34 @@ func (c *common) Cleanup(f func()) {
}
}
+// panicHanding is an argument to runCleanup.
+type panicHandling int
+
+const (
+ normalPanic panicHandling = iota
+ recoverAndReturnPanic
+)
+
// runCleanup is called at the end of the test.
-func (c *common) runCleanup() {
+// If catchPanic is true, this will catch panics, and return the recovered
+// value if any.
+func (c *common) runCleanup(ph panicHandling) (panicVal interface{}) {
c.mu.Lock()
cleanup := c.cleanup
c.cleanup = nil
c.mu.Unlock()
- if cleanup != nil {
- cleanup()
+ if cleanup == nil {
+ return nil
+ }
+
+ if ph == recoverAndReturnPanic {
+ defer func() {
+ panicVal = recover()
+ }()
}
+
+ cleanup()
+ return nil
}
// callerName gives the function name (qualified with a package path)
@@ -938,19 +957,29 @@ func tRunner(t *T, fn func(t *T)) {
}
}
}
- if err != nil {
+
+ doPanic := func(err interface{}) {
t.Fail()
+ if r := t.runCleanup(recoverAndReturnPanic); r != nil {
+ t.Logf("cleanup panicked with %v", r)
+ }
// Flush the output log up to the root before dying.
t.mu.Lock()
root := &t.common
for ; root.parent != nil; root = root.parent {
root.duration += time.Since(root.start)
fmt.Fprintf(root.parent.w, "--- FAIL: %s (%s)\n", root.name, fmtDuration(root.duration))
+ if r := root.parent.runCleanup(recoverAndReturnPanic); r != nil {
+ fmt.Fprintf(root.parent.w, "cleanup panicked with %v", r)
+ }
root.parent.mu.Lock()
io.Copy(root.parent.w, bytes.NewReader(root.output))
}
panic(err)
}
+ if err != nil {
+ doPanic(err)
+ }
t.duration += time.Since(t.start)
@@ -964,6 +993,12 @@ func tRunner(t *T, fn func(t *T)) {
for _, sub := range t.sub {
<-sub.signal
}
+ cleanupStart := time.Now()
+ err := t.runCleanup(recoverAndReturnPanic)
+ t.duration += time.Since(cleanupStart)
+ if err != nil {
+ doPanic(err)
+ }
if !t.isParallel {
// Reacquire the count for sequential tests. See comment in Run.
t.context.waitParallel()
@@ -983,7 +1018,11 @@ func tRunner(t *T, fn func(t *T)) {
}
t.signal <- signal
}()
- defer t.runCleanup()
+ defer func() {
+ if len(t.sub) == 0 {
+ t.runCleanup(normalPanic)
+ }
+ }()
t.start = time.Now()
t.raceErrors = -race.Errors()
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index c64b835..f92ac6f 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -502,6 +502,7 @@ var execTests = []execTest{
{"map MUI64S", "{{index .MUI64S 3}}", "ui643", tVal, true},
{"map MI8S", "{{index .MI8S 3}}", "i83", tVal, true},
{"map MUI8S", "{{index .MUI8S 2}}", "u82", tVal, true},
+ {"index of an interface field", "{{index .Empty3 0}}", "7", tVal, true},
// Slicing.
{"slice[:]", "{{slice .SI}}", "[3 4 5]", tVal, true},
@@ -527,12 +528,14 @@ var execTests = []execTest{
{"string[1:2]", "{{slice .S 1 2}}", "y", tVal, true},
{"out of range", "{{slice .S 1 5}}", "", tVal, false},
{"3-index slice of string", "{{slice .S 1 2 2}}", "", tVal, false},
+ {"slice of an interface field", "{{slice .Empty3 0 1}}", "[7]", tVal, true},
// Len.
{"slice", "{{len .SI}}", "3", tVal, true},
{"map", "{{len .MSI }}", "3", tVal, true},
{"len of int", "{{len 3}}", "", tVal, false},
{"len of nothing", "{{len .Empty0}}", "", tVal, false},
+ {"len of an interface field", "{{len .Empty3}}", "2", tVal, true},
// With.
{"with true", "{{with true}}{{.}}{{end}}", "true", tVal, true},
diff --git a/libgo/go/text/template/funcs.go b/libgo/go/text/template/funcs.go
index 0568c79..46125bc 100644
--- a/libgo/go/text/template/funcs.go
+++ b/libgo/go/text/template/funcs.go
@@ -264,13 +264,13 @@ func slice(item reflect.Value, indexes ...reflect.Value) (reflect.Value, error)
return reflect.Value{}, fmt.Errorf("invalid slice index: %d > %d", idx[0], idx[1])
}
if len(indexes) < 3 {
- return item.Slice(idx[0], idx[1]), nil
+ return v.Slice(idx[0], idx[1]), nil
}
// given item[i:j:k], make sure i <= j <= k.
if idx[1] > idx[2] {
return reflect.Value{}, fmt.Errorf("invalid slice index: %d > %d", idx[1], idx[2])
}
- return item.Slice3(idx[0], idx[1], idx[2]), nil
+ return v.Slice3(idx[0], idx[1], idx[2]), nil
}
// Length
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index 3d57708..30371f2 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -411,7 +411,6 @@ func lexInsideAction(l *lexer) stateFn {
}
case r <= unicode.MaxASCII && unicode.IsPrint(r):
l.emit(itemChar)
- return lexInsideAction
default:
return l.errorf("unrecognized character in action: %#U", r)
}
diff --git a/libgo/go/time/format.go b/libgo/go/time/format.go
index b531cb4..9beb5d9 100644
--- a/libgo/go/time/format.go
+++ b/libgo/go/time/format.go
@@ -792,6 +792,9 @@ func skip(value, prefix string) (string, error) {
// Years must be in the range 0000..9999. The day of the week is checked
// for syntax but it is otherwise ignored.
//
+// For layouts specifying the two-digit year 06, a value NN >= 69 will be treated
+// as 19NN and a value NN < 69 will be treated as 20NN.
+//
// In the absence of a time zone indicator, Parse returns a time in UTC.
//
// When parsing a time with a zone offset like -0700, if the offset corresponds
diff --git a/libgo/go/time/sleep_test.go b/libgo/go/time/sleep_test.go
index 26cc488..9c4de6d 100644
--- a/libgo/go/time/sleep_test.go
+++ b/libgo/go/time/sleep_test.go
@@ -357,7 +357,7 @@ func TestTimerStopStress(t *testing.T) {
for i := 0; i < 100; i++ {
go func(i int) {
timer := AfterFunc(2*Second, func() {
- t.Fatalf("timer %d was not stopped", i)
+ t.Errorf("timer %d was not stopped", i)
})
Sleep(1 * Second)
timer.Stop()
diff --git a/libgo/go/time/time.go b/libgo/go/time/time.go
index 10a132f..5dc9fa6 100644
--- a/libgo/go/time/time.go
+++ b/libgo/go/time/time.go
@@ -1148,6 +1148,9 @@ func (t Time) Zone() (name string, offset int) {
// Unix returns t as a Unix time, the number of seconds elapsed
// since January 1, 1970 UTC. The result does not depend on the
// location associated with t.
+// Unix-like operating systems often record time as a 32-bit
+// count of seconds, but since the method here returns a 64-bit
+// value it is valid for billions of years into the past or future.
func (t Time) Unix() int64 {
return t.unixSec()
}
diff --git a/libgo/go/unicode/utf8/utf8.go b/libgo/go/unicode/utf8/utf8.go
index b722a03..b8368fc 100644
--- a/libgo/go/unicode/utf8/utf8.go
+++ b/libgo/go/unicode/utf8/utf8.go
@@ -14,7 +14,7 @@ package utf8
// Numbers fundamental to the encoding.
const (
RuneError = '\uFFFD' // the "error" Rune or "Unicode replacement character"
- RuneSelf = 0x80 // characters below Runeself are represented as themselves in a single byte.
+ RuneSelf = 0x80 // characters below RuneSelf are represented as themselves in a single byte.
MaxRune = '\U0010FFFF' // Maximum valid Unicode code point.
UTFMax = 4 // maximum number of bytes of a UTF-8 encoded Unicode character.
)