doc/asm.html | 13 +++++++++++-- doc/codewalk/codewalk.xml | 2 +- doc/contribute.html | 14 ++++++++++++-- doc/go1.6.html | 34 ++++++++++++++-------------------- doc/go_faq.html | 2 +- misc/nacl/testzip.proto | 24 ++++++++++++------------ src/cmd/compile/internal/gc/fmt.go | 8 +++++++- src/cmd/compile/internal/gc/gen.go | 2 +- src/cmd/dist/test.go | 5 +++++ src/cmd/go/build.go | 18 ++++++++++++++++++ src/cmd/go/go_test.go | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/cmd/go/main.go | 2 ++ src/cmd/go/pkg.go | 2 +- src/cmd/internal/objfile/disasm.go | 4 ++-- src/cmd/link/internal/ld/dwarf.go | 4 +++- src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile | 0 src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt => src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go | 0 src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go => src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go | 0 src/cmd/vendor/vendor.json => src/cmd/internal/unvendor/vendor.json | 0 src/go/constant/value.go | 2 +- src/go/constant/value_test.go | 2 ++ src/go/internal/gcimporter/gcimporter.go | 6 +++++- src/go/types/expr.go | 8 +++++--- src/go/types/resolver.go | 10 ++++------ src/go/types/testdata/issues.src | 17 +++++++++++++++++ src/net/http/h2_bundle.go | 128 +++++++++++++++++++++++++++++++++++++++++++---------- src/net/http/httptest/server.go | 49 ++++++++++++++++++++++++++++++++++++++++++++----- src/net/http/httptest/server_test.go | 14 ++++++++++++++ src/net/http/request.go | 40 +++++++++++++++++++++++++++------------- src/net/http/serve_test.go | 44 +++++++++++++++++++++++++++++++++++--------- src/net/http/server.go | 12 +++++++----- src/net/http/transport.go | 16 ++++++++++++++++ src/net/http/transport_test.go | 37 ++++++++++++++++++++++++------------- src/net/net_windows_test.go | 117 +++++++++++++++++++++++++++++++++++++++++------------ src/runtime/cgocheck.go | 3 --- src/runtime/crash_test.go | 19 +++++++++++++++++++ src/runtime/crash_unix_test.go | 17 +++++++++++++++-- src/runtime/export_linux_test.go | 1 + src/runtime/export_mmap_test.go | 15 +++++++++++++++ src/runtime/mem_bsd.go | 4 ++-- src/runtime/os2_nacl.go | 25 +++++++++++++------------ src/runtime/os3_solaris.go | 16 +++++++++++++++- src/runtime/pprof/pprof.go | 2 +- src/runtime/runtime-lldb_test.go | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/runtime/runtime_linux_test.go | 13 +++++++++++++ src/runtime/runtime_mmap_test.go | 30 ++++++++++++++++++++++++++++++ src/runtime/stack_test.go | 4 ++-- src/runtime/string.go | 4 ++-- src/runtime/string_test.go | 15 +++++++++++++++ src/runtime/sys_linux_arm64.s | 3 +++ src/runtime/sys_linux_mips64x.s | 1 + src/runtime/sys_linux_ppc64x.s | 1 + src/runtime/sys_nacl_386.s | 3 +++ src/runtime/testdata/testprog/deadlock.go | 20 +++++++++++++++++++- src/runtime/time.go | 2 +- src/runtime/traceback.go | 10 +++++++--- test/fixedbugs/issue14331.dir/a.go | 14 ++++++++++++++ test/fixedbugs/issue14331.dir/b.go | 11 +++++++++++ test/fixedbugs/issue14331.go | 9 +++++++++ test/writebarrier.go | 14 ++++++++++++++ diff --git a/doc/asm.html b/doc/asm.html index 2af2005143f65b09db5801983a129a6afec2631c..392af174c27f0e89a8f263f055c52282428bf228 100644 --- a/doc/asm.html +++ b/doc/asm.html @@ -12,7 +12,7 @@

The assembler is based on the input style of the Plan 9 assemblers, which is documented in detail -elsewhere. +elsewhere. If you plan to write assembly language, you should read that document although much of it is Plan 9-specific. The current document provides a summary of the syntax and the differences with what is explained in that document, and @@ -23,7 +23,7 @@

The most important thing to know about Go's assembler is that it is not a direct representation of the underlying machine. Some of the details map precisely to the machine, but some do not. This is because the compiler suite (see -this description) +this description) needs no assembler pass in the usual pipeline. Instead, the compiler operates on a kind of semi-abstract instruction set, and instruction selection occurs partly after code generation. @@ -620,6 +620,15 @@ These modes accept only 1, 2, 4, and 8 as scale factors. + +

+When using the compiler and assembler's +-dynlink or -shared modes, +any load or store of a fixed memory location such as a global variable +must be assumed to overwrite CX. +Therefore, to be safe for use with these modes, +assembly sources should typically avoid CX except between memory references. +

64-bit Intel 386 (a.k.a. amd64)

diff --git a/doc/codewalk/codewalk.xml b/doc/codewalk/codewalk.xml index 3496db71d76ceed794ad09c96e8684a877a55815..34e6e91938e75a178da63c8547213eeea8b05d18 100644 --- a/doc/codewalk/codewalk.xml +++ b/doc/codewalk/codewalk.xml @@ -91,7 +91,7 @@

The full address syntax is summarized in this table (an excerpt of Table II from - The text editor sam): + The text editor sam):

diff --git a/doc/contribute.html b/doc/contribute.html index a321a8646f09b69b70479f7d1278d2342125aea9..4619c81124a4e54c1e618fcba2b2c93e9cde9907 100644 --- a/doc/contribute.html +++ b/doc/contribute.html @@ -198,14 +198,24 @@ prints help text, not an error.

-Note to Git aficionados: The git-codereview command is not required to +Note to Git aficionados: +The git-codereview command is not required to upload and manage Gerrit code reviews. For those who prefer plain Git, the text -below gives the Git equivalent of each git-codereview command. If you do use plain +below gives the Git equivalent of each git-codereview command. +

+ +

If you do use plain Git, note that you still need the commit hooks that the git-codereview command configures; those hooks add a Gerrit Change-Id line to the commit message and check that all Go source files have been formatted with gofmt. Even if you intend to use plain Git for daily work, install the hooks in a new Git checkout by running git-codereview hooks. +

+ +

+The workflow described below assumes a single change per branch. +It is also possible to prepare a sequence of (usually related) changes in a single branch. +See the git-codereview documentation for details.

Set up git aliases

diff --git a/doc/go1.6.html b/doc/go1.6.html index b4a3900aa088a6a797de63e7a916811057cc9bcc..17c3536aebf7aa11fa2df8164fb77ff5ea3d62f2 100644 --- a/doc/go1.6.html +++ b/doc/go1.6.html @@ -1,5 +1,5 @@ @@ -12,13 +12,6 @@ - -

-NOTE: This is a DRAFT of the Go 1.6 release notes, prepared for the Go 1.6 beta. -Go 1.6 has NOT yet been released. -By our regular schedule, it is expected some time in February 2016. - -

Introduction to Go 1.6

@@ -70,9 +63,12 @@ On NaCl, Go 1.5 required SDK version pepper-41. Go 1.6 adds support for later SDK versions.

-
-TODO: CX no longer available on 386 assembly? (https://golang.org/cl/16386)
-
+

+On 32-bit x86 systems using the -dynlink or -shared compilation modes, +the register CX is now overwritten by certain memory references and should +be avoided in hand-written assembly. +See the assembly documentation for details. +

Tools

@@ -248,7 +244,7 @@ Some programs may run faster, some slower. On average the programs in the Go 1 benchmark suite run a few percent faster in Go 1.6 than they did in Go 1.5. The garbage collector's pauses are even lower than in Go 1.5, -although the effect is likely only noticeable for programs using +especially for programs using a large amount of memory.

@@ -569,7 +565,7 @@ The debug/elf package adds support for general compressed ELF sections. User code needs no updating: the sections are decompressed automatically when read. However, compressed -Section's do not support random access: +Sections do not support random access: they have a nil ReaderAt field. @@ -632,7 +628,6 @@
  • Also in the fmt package, Scanf can now scan hexadecimal strings using %X, as an alias for %x. Both formats accept any mix of upper- and lower-case hexadecimal. -TODO: Keep?
  • @@ -717,9 +712,6 @@ Second, DNS lookup functions such as LookupAddr now return rooted domain names (with a trailing dot) on Plan 9 and Windows, to match the behavior of Go on Unix systems. -TODO: Third, lookups satisfied from /etc/hosts now add a trailing dot as well, -so that looking up 127.0.0.1 typically now returns “localhost.” not “localhost”. -This is arguably a mistake but is not yet fixed. See https://golang.org/issue/13564.
  • @@ -875,16 +867,18 @@
  • The strconv package adds IsGraphic, +similar to IsPrint. +It also adds QuoteToGraphic, QuoteRuneToGraphic, AppendQuoteToGraphic, and AppendQuoteRuneToGraphic, analogous to -IsPrint, -QuoteToPrint, +QuoteToASCII, +QuoteRuneToASCII, and so on. -The Print family escapes all space characters except ASCII space (U+0020). +The ASCII family escapes all space characters except ASCII space (U+0020). In contrast, the Graphic family does not escape any Unicode space characters (category Zs).
  • diff --git a/doc/go_faq.html b/doc/go_faq.html index bcd12075b64c6f946e08be28aa5379c6aacc085a..b5f9772787678949edde8d7c0a089aea88d7fcf9 100644 --- a/doc/go_faq.html +++ b/doc/go_faq.html @@ -98,7 +98,7 @@

    The mascot and logo were designed by Renée French, who also designed -Glenda, +Glenda, the Plan 9 bunny. The gopher is derived from one she used for an WFMU diff --git a/misc/nacl/testzip.proto b/misc/nacl/testzip.proto index c8ab18ea20e7aa4fe94da66e4b3fe812a172ffd9..4e82ac9b4bff89e9803a978494d28c19879aaa22 100644 --- a/misc/nacl/testzip.proto +++ b/misc/nacl/testzip.proto @@ -27,23 +27,23 @@ + internal objfile objfile.go + unvendor + golang.org + x + arch + arm + armasm + testdata + + + x86 + x86asm + testdata + + gofmt gofmt.go gofmt_test.go testdata + - vendor - golang.org - x - arch - arm - armasm - testdata - + - x86 - x86asm - testdata - + archive tar testdata diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index 64b6e36758d6b58445126bc3f9b9e3360834c383..d00e5a6c462d5b590cc81084a382f01e085480e2 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -748,7 +748,13 @@ str := typ if name != "" { str = name + " " + typ } - if flag&obj.FmtShort == 0 && !fmtbody && t.Note != nil { + + // The fmtbody flag is intended to suppress escape analysis annotations + // when printing a function type used in a function body. + // (The escape analysis tags do not apply to func vars.) + // But it must not suppress struct field tags. + // See golang.org/issue/13777 and golang.org/issue/14331. + if flag&obj.FmtShort == 0 && (!fmtbody || !t.Funarg) && t.Note != nil { str += " " + strconv.Quote(*t.Note) } return str diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go index 836834f8bd7be69261e2fcdd553dfaf6c2632932..b7560556683a2de0cb2d0e816f7ad9d2e2368241 100644 --- a/src/cmd/compile/internal/gc/gen.go +++ b/src/cmd/compile/internal/gc/gen.go @@ -836,7 +836,7 @@ case OASWB: Cgen_as_wb(n.Left, n.Right, true) case OAS2DOTTYPE: - cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, false) + cgen_dottype(n.Rlist.N, n.List.N, n.List.Next.N, needwritebarrier(n.List.N, n.Rlist.N)) case OCALLMETH: cgen_callmeth(n, 0) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 156b86810947b8e02bfb381f28742a5de389faff..36c829d1b93c1ca9742646b3438a6372db347caa 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -947,6 +947,11 @@ func (t *tester) raceTest(dt *distTest) error { t.addCmd(dt, "src", "go", "test", "-race", "-i", "runtime/race", "flag", "os/exec") t.addCmd(dt, "src", "go", "test", "-race", "-run=Output", "runtime/race") t.addCmd(dt, "src", "go", "test", "-race", "-short", "-run=TestParse|TestEcho", "flag", "os/exec") + // We don't want the following line, because it + // slows down all.bash (by 10 seconds on my laptop). + // The race builder should catch any error here, but doesn't. + // TODO(iant): Figure out how to catch this. + // t.addCmd(dt, "src", "go", "test", "-race", "-run=TestParallelTest", "cmd/go") if t.cgoEnabled { env := mergeEnvLists([]string{"GOTRACEBACK=2"}, os.Environ()) cmd := t.addCmd(dt, "misc/cgo/test", "go", "test", "-race", "-short") diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index a1f925ed0ba2d7b8c26410150a78bd299c56edb8..f2a2a6014f2b134ce2375846663818e7f956e56f 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -667,6 +667,7 @@ var ( goarch string goos string exeSuffix string + gopath []string ) func init() { @@ -675,6 +676,7 @@ goos = buildContext.GOOS if goos == "windows" { exeSuffix = ".exe" } + gopath = filepath.SplitList(buildContext.GOPATH) } // A builder holds global state about a build. @@ -1684,6 +1686,22 @@ // been built but not installed. inc = append(inc, flag, b.work) // Finally, look in the installed package directories for each action. + // First add the package dirs corresponding to GOPATH entries + // in the original GOPATH order. + need := map[string]*build.Package{} + for _, a1 := range all { + if a1.p != nil && a1.pkgdir == a1.p.build.PkgRoot { + need[a1.p.build.Root] = a1.p.build + } + } + for _, root := range gopath { + if p := need[root]; p != nil && !incMap[p.PkgRoot] { + incMap[p.PkgRoot] = true + inc = append(inc, flag, p.PkgTargetRoot) + } + } + + // Then add anything that's left. for _, a1 := range all { if a1.p == nil { continue diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 6d12f7507396540fb0f4ad77cf4c382f04645c69..39e0f3e56d58b25a6dc4365bf41650fb47e4a70d 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -10,6 +10,7 @@ "flag" "fmt" "go/build" "go/format" + "internal/race" "internal/testenv" "io" "io/ioutil" @@ -69,7 +70,11 @@ func TestMain(m *testing.M) { flag.Parse() if canRun { - out, err := exec.Command("go", "build", "-tags", "testgo", "-o", "testgo"+exeSuffix).CombinedOutput() + args := []string{"build", "-tags", "testgo", "-o", "testgo" + exeSuffix} + if race.Enabled { + args = append(args, "-race") + } + out, err := exec.Command("go", args...).CombinedOutput() if err != nil { fmt.Fprintf(os.Stderr, "building testgo failed: %v\n%s", err, out) os.Exit(2) @@ -2565,6 +2570,59 @@ tg.runFail("install") tg.grepStderr("no install location for.*gopath2.src.test: hidden by .*gopath1.src.test", "missing error") } +func TestGoBuildGOPATHOrder(t *testing.T) { + // golang.org/issue/14176#issuecomment-179895769 + // golang.org/issue/14192 + // -I arguments to compiler could end up not in GOPATH order, + // leading to unexpected import resolution in the compiler. + // This is still not a complete fix (see golang.org/issue/14271 and next test) + // but it is clearly OK and enough to fix both of the two reported + // instances of the underlying problem. It will have to do for now. + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + tg.setenv("GOPATH", tg.path("p1")+string(filepath.ListSeparator)+tg.path("p2")) + + tg.tempFile("p1/src/foo/foo.go", "package foo\n") + tg.tempFile("p2/src/baz/baz.go", "package baz\n") + tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n") + tg.tempFile("p1/src/bar/bar.go", ` + package bar + import _ "baz" + import _ "foo" + `) + + tg.run("install", "-x", "bar") +} + +func TestGoBuildGOPATHOrderBroken(t *testing.T) { + // This test is known not to work. + // See golang.org/issue/14271. + t.Skip("golang.org/issue/14271") + + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + + tg.tempFile("p1/src/foo/foo.go", "package foo\n") + tg.tempFile("p2/src/baz/baz.go", "package baz\n") + tg.tempFile("p1/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/baz.a", "bad\n") + tg.tempFile("p2/pkg/"+runtime.GOOS+"_"+runtime.GOARCH+"/foo.a", "bad\n") + tg.tempFile("p1/src/bar/bar.go", ` + package bar + import _ "baz" + import _ "foo" + `) + + colon := string(filepath.ListSeparator) + tg.setenv("GOPATH", tg.path("p1")+colon+tg.path("p2")) + tg.run("install", "-x", "bar") + + tg.setenv("GOPATH", tg.path("p2")+colon+tg.path("p1")) + tg.run("install", "-x", "bar") +} + func TestIssue11709(t *testing.T) { tg := testgo(t) defer tg.cleanup() @@ -2682,3 +2740,22 @@ tg.run("list", "-f", "{{.Deps}}", pkg) tg.grepStdout("runtime/internal/sys", "did not find required dependency of "+pkg+" on runtime/internal/sys") } } + +// For issue 14337. +func TestParallelTest(t *testing.T) { + tg := testgo(t) + defer tg.cleanup() + tg.makeTempdir() + const testSrc = `package package_test + import ( + "testing" + ) + func TestTest(t *testing.T) { + }` + tg.tempFile("src/p1/p1_test.go", strings.Replace(testSrc, "package_test", "p1_test", 1)) + tg.tempFile("src/p2/p2_test.go", strings.Replace(testSrc, "package_test", "p2_test", 1)) + tg.tempFile("src/p3/p3_test.go", strings.Replace(testSrc, "package_test", "p3_test", 1)) + tg.tempFile("src/p4/p4_test.go", strings.Replace(testSrc, "package_test", "p4_test", 1)) + tg.setenv("GOPATH", tg.path(".")) + tg.run("test", "-p=4", "p1", "p2", "p3", "p4") +} diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index d384594722511028a25ea87d21279a35c72e7468..f9b979da7fba69a500a6db8d5c836c156485dcee 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -454,7 +454,9 @@ } // mergeEnvLists merges the two environment lists such that // variables with the same name in "in" replace those in "out". +// This always returns a newly allocated slice. func mergeEnvLists(in, out []string) []string { + out = append([]string(nil), out...) NextVar: for _, inkv := range in { k := strings.SplitAfterN(inkv, "=", 2)[0] diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go index a804ccd277cfdff699efff776e337543f5f8678c..0c0cf07e71f5c9c28a1f6c0851a54490cd19e126 100644 --- a/src/cmd/go/pkg.go +++ b/src/cmd/go/pkg.go @@ -967,7 +967,7 @@ p.Error.Pos = pos[0].String() } } } - if p.Standard && !p1.Standard && p.Error == nil { + if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil { p.Error = &PackageError{ ImportStack: stk.copy(), Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath), diff --git a/src/cmd/internal/objfile/disasm.go b/src/cmd/internal/objfile/disasm.go index 6495dfb356df2153352c7465ac65ac04842823c7..f038883dc0acebce556eb6e2244b0363778a1579 100644 --- a/src/cmd/internal/objfile/disasm.go +++ b/src/cmd/internal/objfile/disasm.go @@ -15,8 +15,8 @@ "sort" "strings" "text/tabwriter" - "golang.org/x/arch/arm/armasm" - "golang.org/x/arch/x86/x86asm" + "cmd/internal/unvendor/golang.org/x/arch/arm/armasm" + "cmd/internal/unvendor/golang.org/x/arch/x86/x86asm" ) // Disasm is a disassembler for a given File. diff --git a/src/cmd/link/internal/ld/dwarf.go b/src/cmd/link/internal/ld/dwarf.go index 563600d9a2a7c908fc21fb0297c7ea92a2fcaff5..a96b37a4bef32a4558b9543f5f1e314e53445b8c 100644 --- a/src/cmd/link/internal/ld/dwarf.go +++ b/src/cmd/link/internal/ld/dwarf.go @@ -1946,7 +1946,9 @@ * because we need die->offs of dw_globals. */ func writearanges() int64 { sectionstart := Cpos() - headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize))) // don't count unit_length field itself + // The first tuple is aligned to a multiple of the size of a single tuple + // (twice the size of an address) + headersize := int(Rnd(4+2+4+1+1, int64(Thearch.Ptrsize*2))) // don't count unit_length field itself for compunit := dwroot.child; compunit != nil; compunit = compunit.link { b := getattr(compunit, DW_AT_low_pc) diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/Makefile rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/decode.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/decode_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/decode_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/ext_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/ext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/gnu.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/gnu.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/inst.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/inst.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/objdump_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdump_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/objdumpext_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/objdumpext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/plan9x.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/plan9x.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/tables.go rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/tables.go diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/Makefile rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt b/src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt rename from src/cmd/vendor/golang.org/x/arch/arm/armasm/testdata/decode.txt rename to src/cmd/internal/unvendor/golang.org/x/arch/arm/armasm/testdata/decode.txt diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/Makefile rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/decode_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/decode_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/ext_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/ext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/gnu.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/gnu.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/inst_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/inst_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/intel.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/intel.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdump_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdump_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/objdumpext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9ext_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/plan9x_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/tables.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/tables.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/Makefile rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/Makefile diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/decode.txt diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/testdata/libmach8db.c diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/xed_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xed_test.go diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go b/src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go rename from src/cmd/vendor/golang.org/x/arch/x86/x86asm/xedext_test.go rename to src/cmd/internal/unvendor/golang.org/x/arch/x86/x86asm/xedext_test.go diff --git a/src/cmd/vendor/vendor.json b/src/cmd/internal/unvendor/vendor.json rename from src/cmd/vendor/vendor.json rename to src/cmd/internal/unvendor/vendor.json diff --git a/src/go/constant/value.go b/src/go/constant/value.go index 630581047a203f01d6e6c6af3a1b9f543d317a04..310814df71c24fb07e3d92da08ad637925cf4529 100644 --- a/src/go/constant/value.go +++ b/src/go/constant/value.go @@ -96,7 +96,7 @@ // long. Remove the last 3 runes (including the closing '"') by keeping // only the first maxLen-3 runes; then add "...". i := 0 for n := 0; n < maxLen-3; n++ { - _, size := utf8.DecodeRuneInString(s) + _, size := utf8.DecodeRuneInString(s[i:]) i += size } s = s[:i] + "..." diff --git a/src/go/constant/value_test.go b/src/go/constant/value_test.go index de1ab0267a45f4505b7b3235ba0777bbadf08097..dbd96c07a310b8795339c9cd7f3ec55d161967d8 100644 --- a/src/go/constant/value_test.go +++ b/src/go/constant/value_test.go @@ -204,6 +204,7 @@ // ---------------------------------------------------------------------------- // String tests var xxx = strings.Repeat("x", 68) +var issue14262 = `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل). المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد لهذا الترخيص."` var stringTests = []struct { input, short, exact string @@ -225,6 +226,7 @@ {`"foo"`, `"foo"`, `"foo"`}, {`"` + xxx + `xx"`, `"` + xxx + `xx"`, `"` + xxx + `xx"`}, {`"` + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + `xxx"`}, {`"` + xxx + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + xxx + `xxx"`}, + {issue14262, `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة ال...`, issue14262}, // Int {"0", "0", "0"}, diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go index 0ef8eb4fc6ca78bf65f81c0326ad4745e49b20a6..d70ec083c33309beb4394d1edbc62843930716f3 100644 --- a/src/go/internal/gcimporter/gcimporter.go +++ b/src/go/internal/gcimporter/gcimporter.go @@ -31,7 +31,8 @@ var pkgExts = [...]string{".a", ".o"} // FindPkg returns the filename and unique package id for an import // path based on package information provided by build.Import (using -// the build.Default build.Context). +// the build.Default build.Context). A relative srcDir is interpreted +// relative to the current working directory. // If no file was found, an empty filename is returned. // func FindPkg(path, srcDir string) (filename, id string) { @@ -44,6 +45,9 @@ switch { default: // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" // Don't require the source files to be present. + if abs, err := filepath.Abs(srcDir); err == nil { // see issue 14282 + srcDir = abs + } bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary) if bp.PkgObj == "" { return diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 942d3fd5f737040da4a63a12969cddb26cb07f8e..f7c4a173785b531a21a54e93d6e09f1611e03c76 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -184,7 +184,8 @@ // value of the given basic type and for the configuration // provided (only needed for int/uint sizes). // // If rounded != nil, *rounded is set to the rounded value of x for -// representable floating-point values; it is left alone otherwise. +// representable floating-point and complex values, and to an Int +// value for integer values; it is left alone otherwise. // It is ok to provide the addressof the first argument for rounded. func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *constant.Value) bool { if x.Kind() == constant.Unknown { @@ -196,6 +197,9 @@ case isInteger(typ): x := constant.ToInt(x) if x.Kind() != constant.Int { return false + } + if rounded != nil { + *rounded = x } if x, ok := constant.Int64Val(x); ok { switch typ.kind { @@ -808,8 +812,6 @@ yval := y.val typ := x.typ.Underlying().(*Basic) // force integer division of integer operands if op == token.QUO && isInteger(typ) { - xval = constant.ToInt(xval) - yval = constant.ToInt(yval) op = token.QUO_ASSIGN } x.val = constant.BinaryOp(xval, op, yval) diff --git a/src/go/types/resolver.go b/src/go/types/resolver.go index 14148a585b1047be92147d38a3dd100dc686a474..1536df5bf1bebcdc35ce5a2e1282004b050a3027 100644 --- a/src/go/types/resolver.go +++ b/src/go/types/resolver.go @@ -483,11 +483,9 @@ // portion of path. If path is empty, the result is ".". // (Per the go/build package dependency tests, we cannot import // path/filepath and simply use filepath.Dir.) func dir(path string) string { - if i := strings.LastIndexAny(path, "/\\"); i >= 0 { - path = path[:i] - } - if path == "" { - path = "." + if i := strings.LastIndexAny(path, `/\`); i > 0 { + return path[:i] } - return path + // i <= 0 + return "." } diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src index 564d0649b2f73f456ee026d26a98a84672561036..4fe0c629386776b583188ef35bff3f7d9ea7ebf2 100644 --- a/src/go/types/testdata/issues.src +++ b/src/go/types/testdata/issues.src @@ -153,3 +153,20 @@ make(chan I1) <- i0 /* ERROR cannot use .* in send: missing method foo */ make(chan I1) <- i2 /* ERROR cannot use .* in send: wrong type for method foo */ } + +// Check that constants representable as integers are in integer form +// before being used in operations that are only defined on integers. +func issue14229() { + // from the issue + const _ = int64(-1<<63) % 1e6 + + // related + const ( + a int = 3 + b = 4.0 + _ = a / b + _ = a % b + _ = b / a + _ = b % a + ) +} diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go index 11f33cf3b18d9206d374d4c9c71e13171d8376be..4e19b3e71f7d33ca7a9b5e3a594efd203931ae1e 100644 --- a/src/net/http/h2_bundle.go +++ b/src/net/http/h2_bundle.go @@ -1,5 +1,5 @@ -// Code generated by golang.org/x/tools/cmd/bundle command: -// $ bundle golang.org/x/net/http2 net/http http2 +// Code generated by golang.org/x/tools/cmd/bundle. +//go:generate bundle -o h2_bundle.go -prefix http2 -import golang.org/x/net/http2/hpack=internal/golang.org/x/net/http2/hpack golang.org/x/net/http2 // Package http2 implements the HTTP/2 protocol. // @@ -2331,6 +2331,10 @@ '|': true, '~': true, } +type http2connectionStater interface { + ConnectionState() tls.ConnectionState +} + // pipe is a goroutine-safe io.Reader/io.Writer pair. It's like // io.Pipe except there are no PipeReader/PipeWriter halves, and the // underlying buffer is an interface. (io.Pipe is always unbuffered) @@ -2593,28 +2597,76 @@ protoHandler := func(hs *Server, c *tls.Conn, h Handler) { if http2testHookOnConn != nil { http2testHookOnConn() } - conf.handleConn(hs, c, h) + conf.ServeConn(c, &http2ServeConnOpts{ + Handler: h, + BaseConfig: hs, + }) } s.TLSNextProto[http2NextProtoTLS] = protoHandler s.TLSNextProto["h2-14"] = protoHandler return nil } -func (srv *http2Server) handleConn(hs *Server, c net.Conn, h Handler) { +// ServeConnOpts are options for the Server.ServeConn method. +type http2ServeConnOpts struct { + // BaseConfig optionally sets the base configuration + // for values. If nil, defaults are used. + BaseConfig *Server + + // Handler specifies which handler to use for processing + // requests. If nil, BaseConfig.Handler is used. If BaseConfig + // or BaseConfig.Handler is nil, http.DefaultServeMux is used. + Handler Handler +} + +func (o *http2ServeConnOpts) baseConfig() *Server { + if o != nil && o.BaseConfig != nil { + return o.BaseConfig + } + return new(Server) +} + +func (o *http2ServeConnOpts) handler() Handler { + if o != nil { + if o.Handler != nil { + return o.Handler + } + if o.BaseConfig != nil && o.BaseConfig.Handler != nil { + return o.BaseConfig.Handler + } + } + return DefaultServeMux +} + +// ServeConn serves HTTP/2 requests on the provided connection and +// blocks until the connection is no longer readable. +// +// ServeConn starts speaking HTTP/2 assuming that c has not had any +// reads or writes. It writes its initial settings frame and expects +// to be able to read the preface and settings frame from the +// client. If c has a ConnectionState method like a *tls.Conn, the +// ConnectionState is used to verify the TLS ciphersuite and to set +// the Request.TLS field in Handlers. +// +// ServeConn does not support h2c by itself. Any h2c support must be +// implemented in terms of providing a suitably-behaving net.Conn. +// +// The opts parameter is optional. If nil, default values are used. +func (s *http2Server) ServeConn(c net.Conn, opts *http2ServeConnOpts) { sc := &http2serverConn{ - srv: srv, - hs: hs, + srv: s, + hs: opts.baseConfig(), conn: c, remoteAddrStr: c.RemoteAddr().String(), bw: http2newBufferedWriter(c), - handler: h, + handler: opts.handler(), streams: make(map[uint32]*http2stream), readFrameCh: make(chan http2readFrameResult), wantWriteFrameCh: make(chan http2frameWriteMsg, 8), wroteFrameCh: make(chan http2frameWriteResult, 1), bodyReadCh: make(chan http2bodyReadMsg), doneServing: make(chan struct{}), - advMaxStreams: srv.maxConcurrentStreams(), + advMaxStreams: s.maxConcurrentStreams(), writeSched: http2writeScheduler{ maxFrameSize: http2initialMaxFrameSize, }, @@ -2630,10 +2682,10 @@ sc.hpackDecoder = hpack.NewDecoder(http2initialHeaderTableSize, nil) sc.hpackDecoder.SetMaxStringLength(sc.maxHeaderStringLen()) fr := http2NewFramer(sc.bw, c) - fr.SetMaxReadFrameSize(srv.maxReadFrameSize()) + fr.SetMaxReadFrameSize(s.maxReadFrameSize()) sc.framer = fr - if tc, ok := c.(*tls.Conn); ok { + if tc, ok := c.(http2connectionStater); ok { sc.tlsState = new(tls.ConnectionState) *sc.tlsState = tc.ConnectionState() @@ -2646,7 +2698,7 @@ if sc.tlsState.ServerName == "" { } - if !srv.PermitProhibitedCipherSuites && http2isBadCipher(sc.tlsState.CipherSuite) { + if !s.PermitProhibitedCipherSuites && http2isBadCipher(sc.tlsState.CipherSuite) { sc.rejectConn(http2ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite)) return @@ -4874,10 +4926,7 @@ cc.fr = http2NewFramer(cc.bw, cc.br) cc.henc = hpack.NewEncoder(&cc.hbuf) - type connectionStater interface { - ConnectionState() tls.ConnectionState - } - if cs, ok := c.(connectionStater); ok { + if cs, ok := c.(http2connectionStater); ok { state := cs.ConnectionState() cc.tlsState = &state } @@ -5028,7 +5077,27 @@ return 0 } +// checkConnHeaders checks whether req has any invalid connection-level headers. +// per RFC 7540 section 8.1.2.2: Connection-Specific Header Fields. +// Certain headers are special-cased as okay but not transmitted later. +func http2checkConnHeaders(req *Request) error { + if v := req.Header.Get("Upgrade"); v != "" { + return errors.New("http2: invalid Upgrade request header") + } + if v := req.Header.Get("Transfer-Encoding"); (v != "" && v != "chunked") || len(req.Header["Transfer-Encoding"]) > 1 { + return errors.New("http2: invalid Transfer-Encoding request header") + } + if v := req.Header.Get("Connection"); (v != "" && v != "close" && v != "keep-alive") || len(req.Header["Connection"]) > 1 { + return errors.New("http2: invalid Connection request header") + } + return nil +} + func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) { + if err := http2checkConnHeaders(req); err != nil { + return nil, err + } + trailers, err := http2commaSeparatedTrailers(req) if err != nil { return nil, err @@ -5334,10 +5403,14 @@ var didUA bool for k, vv := range req.Header { lowKey := strings.ToLower(k) - if lowKey == "host" || lowKey == "content-length" { + switch lowKey { + case "host", "content-length": + continue - } - if lowKey == "user-agent" { + case "connection", "proxy-connection", "transfer-encoding", "upgrade": + + continue + case "user-agent": didUA = true if len(vv) < 1 { @@ -5445,8 +5518,9 @@ } // clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop. type http2clientConnReadLoop struct { - cc *http2ClientConn - activeRes map[uint32]*http2clientStream // keyed by streamID + cc *http2ClientConn + activeRes map[uint32]*http2clientStream // keyed by streamID + closeWhenIdle bool hdec *hpack.Decoder @@ -5503,7 +5577,7 @@ } func (rl *http2clientConnReadLoop) run() error { cc := rl.cc - closeWhenIdle := cc.t.disableKeepAlives() + rl.closeWhenIdle = cc.t.disableKeepAlives() gotReply := false for { f, err := cc.fr.ReadFrame() @@ -5552,7 +5626,7 @@ } if err != nil { return err } - if closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { + if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 { cc.closeIfIdle() } } @@ -5803,6 +5877,9 @@ code = nil } cs.bufPipe.closeWithErrorAndCode(err, code) delete(rl.activeRes, cs.ID) + if cs.req.Close || cs.req.Header.Get("Connection") == "close" { + rl.closeWhenIdle = true + } } func (cs *http2clientStream) copyTrailers() { @@ -6064,13 +6141,18 @@ // gzipReader wraps a response body so it can lazily // call gzip.NewReader on the first call to Read type http2gzipReader struct { body io.ReadCloser // underlying Response.Body - zr io.Reader // lazily-initialized gzip reader + zr *gzip.Reader // lazily-initialized gzip reader + zerr error // sticky error } func (gz *http2gzipReader) Read(p []byte) (n int, err error) { + if gz.zerr != nil { + return 0, gz.zerr + } if gz.zr == nil { gz.zr, err = gzip.NewReader(gz.body) if err != nil { + gz.zerr = err return 0, err } } diff --git a/src/net/http/httptest/server.go b/src/net/http/httptest/server.go index fabfeca9434f3bf4cd32e060f2a28fc4577ae864..a2573df2510a076bb347b4f13446eee72ec90fed 100644 --- a/src/net/http/httptest/server.go +++ b/src/net/http/httptest/server.go @@ -202,10 +202,31 @@ } // CloseClientConnections closes any open HTTP connections to the test Server. func (s *Server) CloseClientConnections() { + var conns int + ch := make(chan bool) + s.mu.Lock() - defer s.mu.Unlock() for c := range s.conns { - s.closeConn(c) + conns++ + s.closeConnChan(c, ch) + } + s.mu.Unlock() + + // Wait for outstanding closes to finish. + // + // Out of paranoia for making a late change in Go 1.6, we + // bound how long this can wait, since golang.org/issue/14291 + // isn't fully understood yet. At least this should only be used + // in tests. + timer := time.NewTimer(5 * time.Second) + defer timer.Stop() + for i := 0; i < conns; i++ { + select { + case <-ch: + case <-timer.C: + // Too slow. Give up. + return + } } } @@ -267,9 +288,13 @@ } } } -// closeConn closes c. Except on plan9, which is special. See comment below. +// closeConn closes c. // s.mu must be held. -func (s *Server) closeConn(c net.Conn) { +func (s *Server) closeConn(c net.Conn) { s.closeConnChan(c, nil) } + +// closeConnChan is like closeConn, but takes an optional channel to receive a value +// when the goroutine closing c is done. +func (s *Server) closeConnChan(c net.Conn, done chan<- bool) { if runtime.GOOS == "plan9" { // Go's Plan 9 net package isn't great at unblocking reads when // their underlying TCP connections are closed. Don't trust @@ -278,7 +303,21 @@ // StateClosed. Instead, just go there directly. Plan 9 may leak // resources if the syscall doesn't end up returning. Oh well. s.forgetConn(c) } - go c.Close() + + // Somewhere in the chaos of https://golang.org/cl/15151 we found that + // some types of conns were blocking in Close too long (or deadlocking?) + // and we had to call Close in a goroutine. I (bradfitz) forget what + // that was at this point, but I suspect it was *tls.Conns, which + // were later fixed in https://golang.org/cl/18572, so this goroutine + // is _probably_ unnecessary now. But it's too late in Go 1.6 too remove + // it with confidence. + // TODO(bradfitz): try to remove it for Go 1.7. (golang.org/issue/14291) + go func() { + c.Close() + if done != nil { + done <- true + } + }() } // forgetConn removes c from the set of tracked conns and decrements it from the diff --git a/src/net/http/httptest/server_test.go b/src/net/http/httptest/server_test.go index 6ffc671e575241ac332af94148eba2da24b33e77..c9606f24198d1cf7b5af67b6495494572b483fd4 100644 --- a/src/net/http/httptest/server_test.go +++ b/src/net/http/httptest/server_test.go @@ -84,3 +84,17 @@ } ts.Close() // test we don't hang here forever. } + +// Issue 14290 +func TestServerCloseClientConnections(t *testing.T) { + var s *Server + s = NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + s.CloseClientConnections() + })) + defer s.Close() + res, err := http.Get(s.URL) + if err == nil { + res.Body.Close() + t.Fatal("Unexpected response: %#v", res) + } +} diff --git a/src/net/http/request.go b/src/net/http/request.go index 16c5bb43ac4d4c7b7974dfa0c6e1c50c0c28eef3..8cdab02af5a057ca0382fcb17034a4086547a421 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -99,30 +99,37 @@ Proto string // "HTTP/1.0" ProtoMajor int // 1 ProtoMinor int // 0 - // A header maps request lines to their values. - // If the header says + // Header contains the request header fields either received + // by the server or to be sent by the client. // + // If a server received a request with header lines, + // + // Host: example.com // accept-encoding: gzip, deflate // Accept-Language: en-us - // Connection: keep-alive + // fOO: Bar + // foo: two // // then // // Header = map[string][]string{ // "Accept-Encoding": {"gzip, deflate"}, // "Accept-Language": {"en-us"}, - // "Connection": {"keep-alive"}, + // "Foo": {"Bar", "two"}, // } // - // HTTP defines that header names are case-insensitive. - // The request parser implements this by canonicalizing the - // name, making the first character and any characters - // following a hyphen uppercase and the rest lowercase. + // For incoming requests, the Host header is promoted to the + // Request.Host field and removed from the Header map. // - // For client requests certain headers are automatically - // added and may override values in Header. + // HTTP defines that header names are case-insensitive. The + // request parser implements this by using CanonicalHeaderKey, + // making the first character and any characters following a + // hyphen uppercase and the rest lowercase. // - // See the documentation for the Request.Write method. + // For client requests, certain headers such as Content-Length + // and Connection are automatically written when needed and + // values in Header may be ignored. See the documentation + // for the Request.Write method. Header Header // Body is the request's body. @@ -152,8 +159,15 @@ // receiving requests. TransferEncoding []string // Close indicates whether to close the connection after - // replying to this request (for servers) or after sending - // the request (for clients). + // replying to this request (for servers) or after sending this + // request and reading its response (for clients). + // + // For server requests, the HTTP server handles this automatically + // and this field is not needed by Handlers. + // + // For client requests, setting this field prevents re-use of + // TCP connections between requests to the same hosts, as if + // Transport.DisableKeepAlives were set. Close bool // For server requests Host specifies the host on which the diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index f8cad802d4986a9293c533284c6ca59bc99a342c..384b453ce0ad5860a2fc67ff01537c700145c325 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -1039,12 +1039,30 @@ } } func TestAutomaticHTTP2_ListenAndServe(t *testing.T) { - defer afterTest(t) - defer SetTestHookServerServe(nil) cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) if err != nil { t.Fatal(err) } + testAutomaticHTTP2_ListenAndServe(t, &tls.Config{ + Certificates: []tls.Certificate{cert}, + }) +} + +func TestAutomaticHTTP2_ListenAndServe_GetCertificate(t *testing.T) { + cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) + if err != nil { + t.Fatal(err) + } + testAutomaticHTTP2_ListenAndServe(t, &tls.Config{ + GetCertificate: func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) { + return &cert, nil + }, + }) +} + +func testAutomaticHTTP2_ListenAndServe(t *testing.T, tlsConf *tls.Config) { + defer afterTest(t) + defer SetTestHookServerServe(nil) var ok bool var s *Server const maxTries = 5 @@ -1060,10 +1078,8 @@ SetTestHookServerServe(func(s *Server, ln net.Listener) { lnc <- ln }) s = &Server{ - Addr: addr, - TLSConfig: &tls.Config{ - Certificates: []tls.Certificate{cert}, - }, + Addr: addr, + TLSConfig: tlsConf, } errc := make(chan error, 1) go func() { errc <- s.ListenAndServeTLS("", "") }() @@ -2416,7 +2432,7 @@ conn, err := net.Dial("tcp", ts.Listener.Addr().String()) if err != nil { t.Fatalf("error dialing: %v", err) } - diec := make(chan bool, 2) + diec := make(chan bool, 1) go func() { const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n" _, err = io.WriteString(conn, req+req) // two requests @@ -2426,13 +2442,23 @@ } <-diec conn.Close() }() + reqs := 0 + closes := 0 For: for { select { case <-gotReq: - diec <- true + reqs++ + if reqs > 2 { + t.Fatal("too many requests") + } else if reqs > 1 { + diec <- true + } case <-sawClose: - break For + closes++ + if closes > 1 { + break For + } case <-time.After(5 * time.Second): ts.CloseClientConnections() t.Fatal("timeout") diff --git a/src/net/http/server.go b/src/net/http/server.go index 004a1f92fc4da31f03a67360b16acc51b4dd4117..5e3b6084ae3879be3b14ca5d3dfaddce652256b4 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2233,10 +2233,11 @@ // then calls Serve to handle requests on incoming TLS connections. // Accepted connections are configured to enable TCP keep-alives. // // Filenames containing a certificate and matching private key for the -// server must be provided if the Server's TLSConfig.Certificates is -// not populated. If the certificate is signed by a certificate -// authority, the certFile should be the concatenation of the server's -// certificate, any intermediates, and the CA's certificate. +// server must be provided if neither the Server's TLSConfig.Certificates +// nor TLSConfig.GetCertificate are populated. If the certificate is +// signed by a certificate authority, the certFile should be the +// concatenation of the server's certificate, any intermediates, and +// the CA's certificate. // // If srv.Addr is blank, ":https" is used. // @@ -2258,7 +2259,8 @@ if !strSliceContains(config.NextProtos, "http/1.1") { config.NextProtos = append(config.NextProtos, "http/1.1") } - if len(config.Certificates) == 0 || certFile != "" || keyFile != "" { + configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil + if !configHasCert || certFile != "" || keyFile != "" { var err error config.Certificates = make([]tls.Certificate, 1) config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) diff --git a/src/net/http/transport.go b/src/net/http/transport.go index 41df906cf2d1d70d3fa1d714ebc4b706f0c692ef..baf71d5e85e2facf97294f64fa41dfdbdcc4c0b3 100644 --- a/src/net/http/transport.go +++ b/src/net/http/transport.go @@ -163,6 +163,22 @@ if strings.Contains(os.Getenv("GODEBUG"), "http2client=0") { return } if t.TLSNextProto != nil { + // This is the documented way to disable http2 on a + // Transport. + return + } + if t.TLSClientConfig != nil { + // Be conservative for now (for Go 1.6) at least and + // don't automatically enable http2 if they've + // specified a custom TLS config. Let them opt-in + // themselves via http2.ConfigureTransport so we don't + // surprise them by modifying their tls.Config. + // Issue 14275. + return + } + if t.ExpectContinueTimeout != 0 { + // Unsupported in http2, so disable http2 for now. + // Issue 13851. return } t2, err := http2configureTransport(t) diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go index 8cb89a4220b7ca554cca0b5f1cd95863d1cb79c9..0c901b30a44771528860e54926b0fe683a66a5ac 100644 --- a/src/net/http/transport_test.go +++ b/src/net/http/transport_test.go @@ -2885,23 +2885,34 @@ } } func TestTransportAutomaticHTTP2(t *testing.T) { - tr := &Transport{} - _, err := tr.RoundTrip(new(Request)) - if err == nil { - t.Error("expected error from RoundTrip") - } - if tr.TLSNextProto["h2"] == nil { - t.Errorf("HTTP/2 not registered.") - } + testTransportAutoHTTP(t, &Transport{}, true) +} + +func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) { + testTransportAutoHTTP(t, &Transport{ + TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper), + }, false) +} + +func TestTransportAutomaticHTTP2_TLSConfig(t *testing.T) { + testTransportAutoHTTP(t, &Transport{ + TLSClientConfig: new(tls.Config), + }, false) +} + +func TestTransportAutomaticHTTP2_ExpectContinueTimeout(t *testing.T) { + testTransportAutoHTTP(t, &Transport{ + ExpectContinueTimeout: 1 * time.Second, + }, false) +} - // Now with TLSNextProto set: - tr = &Transport{TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper)} - _, err = tr.RoundTrip(new(Request)) +func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) { + _, err := tr.RoundTrip(new(Request)) if err == nil { t.Error("expected error from RoundTrip") } - if tr.TLSNextProto["h2"] != nil { - t.Errorf("HTTP/2 registered, despite non-nil TLSNextProto field") + if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 { + t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2) } } diff --git a/src/net/net_windows_test.go b/src/net/net_windows_test.go index 095a339e02c8e69a8a258526733ee94d8a92bd1e..df390327218e3307a97609ff65f51bc1e505c3b7 100644 --- a/src/net/net_windows_test.go +++ b/src/net/net_windows_test.go @@ -314,20 +314,43 @@ t.Fatalf("unexpected interface list %q, want %q", have, want) } } -func netshInterfaceIPv4ShowAddress(name string) ([]string, error) { - out, err := runCmd("netsh", "interface", "ipv4", "show", "address", "name=\""+name+"\"") - if err != nil { - return nil, err - } +func netshInterfaceIPv4ShowAddress(name string, netshOutput []byte) []string { // adress information is listed like: + // + //Configuration for interface "Local Area Connection" + // DHCP enabled: Yes // IP Address: 10.0.0.2 // Subnet Prefix: 10.0.0.0/24 (mask 255.255.255.0) // IP Address: 10.0.0.3 // Subnet Prefix: 10.0.0.0/24 (mask 255.255.255.0) + // Default Gateway: 10.0.0.254 + // Gateway Metric: 0 + // InterfaceMetric: 10 + // + //Configuration for interface "Loopback Pseudo-Interface 1" + // DHCP enabled: No + // IP Address: 127.0.0.1 + // Subnet Prefix: 127.0.0.0/8 (mask 255.0.0.0) + // InterfaceMetric: 50 + // addrs := make([]string, 0) var addr, subnetprefix string - lines := bytes.Split(out, []byte{'\r', '\n'}) + var processingOurInterface bool + lines := bytes.Split(netshOutput, []byte{'\r', '\n'}) for _, line := range lines { + if !processingOurInterface { + if !bytes.HasPrefix(line, []byte("Configuration for interface")) { + continue + } + if !bytes.Contains(line, []byte(`"`+name+`"`)) { + continue + } + processingOurInterface = true + continue + } + if len(line) == 0 { + break + } if bytes.Contains(line, []byte("Subnet Prefix:")) { f := bytes.Split(line, []byte{':'}) if len(f) == 2 { @@ -351,18 +374,50 @@ addr = string(bytes.TrimSpace(f[1])) } } } - return addrs, nil + return addrs } -func netshInterfaceIPv6ShowAddress(name string) ([]string, error) { +func netshInterfaceIPv6ShowAddress(name string, netshOutput []byte) []string { + // adress information is listed like: + // + //Address ::1 Parameters + //--------------------------------------------------------- + //Interface Luid : Loopback Pseudo-Interface 1 + //Scope Id : 0.0 + //Valid Lifetime : infinite + //Preferred Lifetime : infinite + //DAD State : Preferred + //Address Type : Other + //Skip as Source : false + // + //Address XXXX::XXXX:XXXX:XXXX:XXXX%11 Parameters + //--------------------------------------------------------- + //Interface Luid : Local Area Connection + //Scope Id : 0.11 + //Valid Lifetime : infinite + //Preferred Lifetime : infinite + //DAD State : Preferred + //Address Type : Other + //Skip as Source : false + // + // TODO: need to test ipv6 netmask too, but netsh does not outputs it - out, err := runCmd("netsh", "interface", "ipv6", "show", "address", "interface=\""+name+"\"") - if err != nil { - return nil, err - } + var addr string addrs := make([]string, 0) - lines := bytes.Split(out, []byte{'\r', '\n'}) + lines := bytes.Split(netshOutput, []byte{'\r', '\n'}) for _, line := range lines { + if addr != "" { + if len(line) == 0 { + addr = "" + continue + } + if string(line) != "Interface Luid : "+name { + continue + } + addrs = append(addrs, addr) + addr = "" + continue + } if !bytes.HasPrefix(line, []byte("Address")) { continue } @@ -383,9 +438,9 @@ if ipv4Tail.Match(f[0]) { f[0] = []byte(ParseIP(string(f[0])).String()) } - addrs = append(addrs, string(bytes.ToLower(bytes.TrimSpace(f[0])))) + addr = string(bytes.ToLower(bytes.TrimSpace(f[0]))) } - return addrs, nil + return addrs } func TestInterfaceAddrsWithNetsh(t *testing.T) { @@ -395,6 +450,16 @@ } if !isEnglishOS(t) { t.Skip("English version of OS required for this test") } + + outIPV4, err := runCmd("netsh", "interface", "ipv4", "show", "address") + if err != nil { + t.Fatal(err) + } + outIPV6, err := runCmd("netsh", "interface", "ipv6", "show", "address", "level=verbose") + if err != nil { + t.Fatal(err) + } + ift, err := Interfaces() if err != nil { t.Fatal(err) @@ -431,14 +496,8 @@ } } sort.Strings(have) - want, err := netshInterfaceIPv4ShowAddress(ifi.Name) - if err != nil { - t.Fatal(err) - } - wantIPv6, err := netshInterfaceIPv6ShowAddress(ifi.Name) - if err != nil { - t.Fatal(err) - } + want := netshInterfaceIPv4ShowAddress(ifi.Name, outIPV4) + wantIPv6 := netshInterfaceIPv6ShowAddress(ifi.Name, outIPV6) want = append(want, wantIPv6...) sort.Strings(want) @@ -487,8 +546,13 @@ //Transport Name: Media disconnected // //Connection Name: Bluetooth Network Connection //Network Adapter: Bluetooth Device (Personal Area Network) - //Physical Address: XX-XX-XX-XX-XX-XX - //Transport Name: Media disconnected + //Physical Address: N/A + //Transport Name: Hardware not present + // + //Connection Name: VMware Network Adapter VMnet8 + //Network Adapter: VMware Virtual Ethernet Adapter for VMnet8 + //Physical Address: Disabled + //Transport Name: Disconnected // want := make(map[string]string) var name string @@ -515,6 +579,9 @@ } addr := string(bytes.ToLower(bytes.TrimSpace(f[1]))) if addr == "" { t.Fatal("empty address on \"Physical Address\" line: %q", line) + } + if addr == "disabled" || addr == "n/a" { + continue } addr = strings.Replace(addr, "-", ":", -1) want[name] = addr diff --git a/src/runtime/cgocheck.go b/src/runtime/cgocheck.go index 0077e22332633fd3fa30da5e9e0f04f24af3dba5..aebce1506d17e389e34ebcad0551327cfb331a61 100644 --- a/src/runtime/cgocheck.go +++ b/src/runtime/cgocheck.go @@ -135,9 +135,6 @@ hbits := heapBitsForAddr(uintptr(src)) for i := uintptr(0); i < off+size; i += sys.PtrSize { bits := hbits.bits() - if bits != 0 { - println(i, bits) - } if i >= off && bits&bitPointer != 0 { v := *(*unsafe.Pointer)(add(src, i)) if cgoIsGoPointer(v) { diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go index b622eb4526a8d63bbb5d846d9f0451a713636c13..5f0e77b0dc33590536cefd39264eb5255eeaa09d 100644 --- a/src/runtime/crash_test.go +++ b/src/runtime/crash_test.go @@ -317,3 +317,22 @@ if !strings.HasSuffix(output, want) { t.Fatalf("output does not start with %q:\n%s", want, output) } } + +func TestPanicTraceback(t *testing.T) { + output := runTestProg(t, "testprog", "PanicTraceback") + want := "panic: hello" + if !strings.HasPrefix(output, want) { + t.Fatalf("output does not start with %q:\n%s", want, output) + } + + // Check functions in the traceback. + fns := []string{"panic", "main.pt1.func1", "panic", "main.pt2.func1", "panic", "main.pt2", "main.pt1"} + for _, fn := range fns { + re := regexp.MustCompile(`(?m)^` + regexp.QuoteMeta(fn) + `\(.*\n`) + idx := re.FindStringIndex(output) + if idx == nil { + t.Fatalf("expected %q function in traceback:\n%s", fn, output) + } + output = output[idx[1]:] + } +} diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go index 5284a37b0f141721060c5e6a03098a4cd83c6f4c..771b303f6ee39aee0025469353f698d497f736c1 100644 --- a/src/runtime/crash_unix_test.go +++ b/src/runtime/crash_unix_test.go @@ -14,6 +14,7 @@ "os" "os/exec" "path/filepath" "runtime" + "strings" "syscall" "testing" ) @@ -52,6 +53,18 @@ cmd = exec.Command(filepath.Join(dir, "a.exe")) cmd = testEnv(cmd) cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") + + // Set GOGC=off. Because of golang.org/issue/10958, the tight + // loops in the test program are not preemptible. If GC kicks + // in, it may lock up and prevent main from saying it's ready. + newEnv := []string{} + for _, s := range cmd.Env { + if !strings.HasPrefix(s, "GOGC=") { + newEnv = append(newEnv, s) + } + } + cmd.Env = append(newEnv, "GOGC=off") + var outbuf bytes.Buffer cmd.Stdout = &outbuf cmd.Stderr = &outbuf @@ -137,8 +150,8 @@ func TestSignalExitStatus(t *testing.T) { testenv.MustHaveGoBuild(t) switch runtime.GOOS { - case "netbsd": - t.Skip("skipping on NetBSD; see https://golang.org/issue/14063") + case "netbsd", "solaris": + t.Skipf("skipping on %s; see https://golang.org/issue/14063", runtime.GOOS) } exe, err := buildTestProg(t, "testprog") if err != nil { diff --git a/src/runtime/export_linux_test.go b/src/runtime/export_linux_test.go index c8b97466764597482126f6c3723321393dc43dcf..61d6ae4bf2f0d64c083351693a67a57724335158 100644 --- a/src/runtime/export_linux_test.go +++ b/src/runtime/export_linux_test.go @@ -7,3 +7,4 @@ package runtime var NewOSProc0 = newosproc0 +var Mincore = mincore diff --git a/src/runtime/export_mmap_test.go b/src/runtime/export_mmap_test.go new file mode 100644 index 0000000000000000000000000000000000000000..11ea076f0bac37547a4d1eb81d07b0fc4d8aba5e --- /dev/null +++ b/src/runtime/export_mmap_test.go @@ -0,0 +1,15 @@ +// Copyright 2016 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +// Export guts for testing. + +package runtime + +var Mmap = mmap + +const ENOMEM = _ENOMEM +const MAP_ANON = _MAP_ANON +const MAP_PRIVATE = _MAP_PRIVATE diff --git a/src/runtime/mem_bsd.go b/src/runtime/mem_bsd.go index 1e388ec7281646e8f63141d3132bd2390554aa23..c3fe6106d7dcf66816eec9dfa48e10526dd56d12 100644 --- a/src/runtime/mem_bsd.go +++ b/src/runtime/mem_bsd.go @@ -59,9 +59,9 @@ *reserved = true return p } -func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) { - const _ENOMEM = 12 +const _ENOMEM = 12 +func sysMap(v unsafe.Pointer, n uintptr, reserved bool, sysStat *uint64) { mSysStatInc(sysStat, n) // On 64-bit, we don't actually have v reserved, so tread carefully. diff --git a/src/runtime/os2_nacl.go b/src/runtime/os2_nacl.go index 0c91e0f7372dba8444fd6fdb0b3fba26718fb48c..d8c88db0adf7258ce3d835d2486d89552d93ce97 100644 --- a/src/runtime/os2_nacl.go +++ b/src/runtime/os2_nacl.go @@ -10,18 +10,19 @@ _SI_USER = 1 // native_client/src/trusted/service_runtime/include/sys/errno.h // The errors are mainly copied from Linux. - _EPERM = 1 /* Operation not permitted */ - _ENOENT = 2 /* No such file or directory */ - _ESRCH = 3 /* No such process */ - _EINTR = 4 /* Interrupted system call */ - _EIO = 5 /* I/O error */ - _ENXIO = 6 /* No such device or address */ - _E2BIG = 7 /* Argument list too long */ - _ENOEXEC = 8 /* Exec format error */ - _EBADF = 9 /* Bad file number */ - _ECHILD = 10 /* No child processes */ - _EAGAIN = 11 /* Try again */ - _ENOMEM = 12 /* Out of memory */ + _EPERM = 1 /* Operation not permitted */ + _ENOENT = 2 /* No such file or directory */ + _ESRCH = 3 /* No such process */ + _EINTR = 4 /* Interrupted system call */ + _EIO = 5 /* I/O error */ + _ENXIO = 6 /* No such device or address */ + _E2BIG = 7 /* Argument list too long */ + _ENOEXEC = 8 /* Exec format error */ + _EBADF = 9 /* Bad file number */ + _ECHILD = 10 /* No child processes */ + _EAGAIN = 11 /* Try again */ + // _ENOMEM is defined in mem_bsd.go for nacl. + // _ENOMEM = 12 /* Out of memory */ _EACCES = 13 /* Permission denied */ _EFAULT = 14 /* Bad address */ _EBUSY = 16 /* Device or resource busy */ diff --git a/src/runtime/os3_solaris.go b/src/runtime/os3_solaris.go index 7bda07bd4a5b793f9473adf3a4c5be46a12deb71..7ebb35c8e9c462e741dd7c0f93904f5c5c9dc26e 100644 --- a/src/runtime/os3_solaris.go +++ b/src/runtime/os3_solaris.go @@ -442,7 +442,21 @@ } //go:nosplit func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer { - return unsafe.Pointer(sysvicall6(&libc_mmap, uintptr(addr), uintptr(n), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off))) + p, err := doMmap(uintptr(addr), n, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(off)) + if p == ^uintptr(0) { + return unsafe.Pointer(err) + } + return unsafe.Pointer(p) +} + +//go:nosplit +func doMmap(addr, n, prot, flags, fd, off uintptr) (uintptr, uintptr) { + var libcall libcall + libcall.fn = uintptr(unsafe.Pointer(&libc_mmap)) + libcall.n = 6 + libcall.args = uintptr(noescape(unsafe.Pointer(&addr))) + asmcgocall(unsafe.Pointer(&asmsysvicall6), unsafe.Pointer(&libcall)) + return libcall.r1, libcall.err } //go:nosplit diff --git a/src/runtime/pprof/pprof.go b/src/runtime/pprof/pprof.go index 7d677cb64e6c23e856d8d1f0bd9346e4ad3eeb4c..e09a33d5d9f8242f538a880257c1239daf992cba 100644 --- a/src/runtime/pprof/pprof.go +++ b/src/runtime/pprof/pprof.go @@ -346,7 +346,7 @@ file, line := f.FileLine(tracepc) name := f.Name() // Hide runtime.goexit and any runtime functions at the beginning. // This is useful mainly for allocation traces. - wasPanic = name == "runtime.panic" + wasPanic = name == "runtime.gopanic" if name == "runtime.goexit" || !show && strings.HasPrefix(name, "runtime.") { continue } diff --git a/src/runtime/runtime-lldb_test.go b/src/runtime/runtime-lldb_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2bd91c1ec03893f3f03857dd0cf6f3659f97de81 --- /dev/null +++ b/src/runtime/runtime-lldb_test.go @@ -0,0 +1,262 @@ +// Copyright 2016 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 ( + "debug/elf" + "debug/macho" + "encoding/binary" + "internal/testenv" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime" + "strings" + "testing" +) + +var lldbPath string + +func checkLldbPython(t *testing.T) { + cmd := exec.Command("lldb", "-P") + out, err := cmd.CombinedOutput() + if err != nil { + t.Skipf("skipping due to issue running lldb: %v\n%s", err, out) + } + lldbPath = strings.TrimSpace(string(out)) + + cmd = exec.Command("/usr/bin/python2.7", "-c", "import sys;sys.path.append(sys.argv[1]);import lldb; print('go lldb python support')", lldbPath) + out, err = cmd.CombinedOutput() + + if err != nil { + t.Skipf("skipping due to issue running python: %v\n%s", err, out) + } + if string(out) != "go lldb python support\n" { + t.Skipf("skipping due to lack of python lldb support: %s", out) + } + + if runtime.GOOS == "darwin" { + // Try to see if we have debugging permissions. + cmd = exec.Command("/usr/sbin/DevToolsSecurity", "-status") + out, err = cmd.CombinedOutput() + if err != nil { + t.Skipf("DevToolsSecurity failed: %v", err) + } else if !strings.Contains(string(out), "enabled") { + t.Skip(string(out)) + } + cmd = exec.Command("/usr/bin/groups") + out, err = cmd.CombinedOutput() + if err != nil { + t.Skipf("groups failed: %v", err) + } else if !strings.Contains(string(out), "_developer") { + t.Skip("Not in _developer group") + } + } +} + +const lldbHelloSource = ` +package main +import "fmt" +func main() { + mapvar := make(map[string]string,5) + mapvar["abc"] = "def" + mapvar["ghi"] = "jkl" + intvar := 42 + ptrvar := &intvar + fmt.Println("hi") // line 10 + _ = ptrvar +} +` + +const lldbScriptSource = ` +import sys +sys.path.append(sys.argv[1]) +import lldb +import os + +TIMEOUT_SECS = 5 + +debugger = lldb.SBDebugger.Create() +debugger.SetAsync(True) +target = debugger.CreateTargetWithFileAndArch("a.exe", None) +if target: + print "Created target" + main_bp = target.BreakpointCreateByLocation("main.go", 10) + if main_bp: + print "Created breakpoint" + process = target.LaunchSimple(None, None, os.getcwd()) + if process: + print "Process launched" + listener = debugger.GetListener() + process.broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged) + while True: + event = lldb.SBEvent() + if listener.WaitForEvent(TIMEOUT_SECS, event): + if lldb.SBProcess.GetRestartedFromEvent(event): + continue + state = process.GetState() + if state in [lldb.eStateUnloaded, lldb.eStateLaunching, lldb.eStateRunning]: + continue + else: + print "Timeout launching" + break + if state == lldb.eStateStopped: + for t in process.threads: + if t.GetStopReason() == lldb.eStopReasonBreakpoint: + print "Hit breakpoint" + frame = t.GetFrameAtIndex(0) + if frame: + if frame.line_entry: + print "Stopped at %s:%d" % (frame.line_entry.file.basename, frame.line_entry.line) + if frame.function: + print "Stopped in %s" % (frame.function.name,) + var = frame.FindVariable('intvar') + if var: + print "intvar = %s" % (var.GetValue(),) + else: + print "no intvar" + else: + print "Process state", state + process.Destroy() +else: + print "Failed to create target a.exe" + +lldb.SBDebugger.Destroy(debugger) +sys.exit() +` + +const expectedLldbOutput = `Created target +Created breakpoint +Process launched +Hit breakpoint +Stopped at main.go:10 +Stopped in main.main +intvar = 42 +` + +func TestLldbPython(t *testing.T) { + testenv.MustHaveGoBuild(t) + if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final { + t.Skip("gdb test can fail with GOROOT_FINAL pending") + } + + checkLldbPython(t) + + dir, err := ioutil.TempDir("", "go-build") + if err != nil { + t.Fatalf("failed to create temp directory: %v", err) + } + defer os.RemoveAll(dir) + + src := filepath.Join(dir, "main.go") + err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644) + if err != nil { + t.Fatalf("failed to create file: %v", err) + } + + cmd := exec.Command("go", "build", "-gcflags", "-N -l", "-o", "a.exe") + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("building source %v\n%s", err, out) + } + + src = filepath.Join(dir, "script.py") + err = ioutil.WriteFile(src, []byte(lldbScriptSource), 0755) + if err != nil { + t.Fatalf("failed to create script: %v", err) + } + + cmd = exec.Command("/usr/bin/python2.7", "script.py", lldbPath) + cmd.Dir = dir + got, _ := cmd.CombinedOutput() + + if string(got) != expectedLldbOutput { + if strings.Contains(string(got), "Timeout launching") { + t.Skip("Timeout launching") + } + t.Fatalf("Unexpected lldb output:\n%s", got) + } +} + +// Check that aranges are valid even when lldb isn't installed. +func TestDwarfAranges(t *testing.T) { + testenv.MustHaveGoBuild(t) + dir, err := ioutil.TempDir("", "go-build") + if err != nil { + t.Fatalf("failed to create temp directory: %v", err) + } + defer os.RemoveAll(dir) + + src := filepath.Join(dir, "main.go") + err = ioutil.WriteFile(src, []byte(lldbHelloSource), 0644) + if err != nil { + t.Fatalf("failed to create file: %v", err) + } + + cmd := exec.Command("go", "build", "-o", "a.exe") + cmd.Dir = dir + out, err := cmd.CombinedOutput() + if err != nil { + t.Fatalf("building source %v\n%s", err, out) + } + + filename := filepath.Join(dir, "a.exe") + if f, err := elf.Open(filename); err == nil { + sect := f.Section(".debug_aranges") + if sect == nil { + t.Fatal("Missing aranges section") + } + verifyAranges(t, f.ByteOrder, sect.Open()) + } else if f, err := macho.Open(filename); err == nil { + sect := f.Section("__debug_aranges") + if sect == nil { + t.Fatal("Missing aranges section") + } + verifyAranges(t, f.ByteOrder, sect.Open()) + } else { + t.Skip("Not an elf or macho binary.") + } +} + +func verifyAranges(t *testing.T, byteorder binary.ByteOrder, data io.ReadSeeker) { + var header struct { + UnitLength uint32 // does not include the UnitLength field + Version uint16 + Offset uint32 + AddressSize uint8 + SegmentSize uint8 + } + for { + offset, err := data.Seek(0, 1) + if err != nil { + t.Fatalf("Seek error: %v", err) + } + if err = binary.Read(data, byteorder, &header); err == io.EOF { + return + } else if err != nil { + t.Fatalf("Error reading arange header: %v", err) + } + tupleSize := int64(header.SegmentSize) + 2*int64(header.AddressSize) + lastTupleOffset := offset + int64(header.UnitLength) + 4 - tupleSize + if lastTupleOffset%tupleSize != 0 { + t.Fatalf("Invalid arange length %d, (addr %d, seg %d)", header.UnitLength, header.AddressSize, header.SegmentSize) + } + if _, err = data.Seek(lastTupleOffset, 0); err != nil { + t.Fatalf("Seek error: %v", err) + } + buf := make([]byte, tupleSize) + if n, err := data.Read(buf); err != nil || int64(n) < tupleSize { + t.Fatalf("Read error: %v", err) + } + for _, val := range buf { + if val != 0 { + t.Fatalf("Invalid terminator") + } + } + } +} diff --git a/src/runtime/runtime_linux_test.go b/src/runtime/runtime_linux_test.go index 5344ed2051a7cf09bc3cd564b3fbe4bdb62834aa..58c797f1dd6d2d0f0531667d480bc059bae1cf59 100644 --- a/src/runtime/runtime_linux_test.go +++ b/src/runtime/runtime_linux_test.go @@ -8,6 +8,7 @@ import ( . "runtime" "syscall" "testing" + "unsafe" ) var pid, tid int @@ -27,3 +28,15 @@ if pid != tid { t.Fatalf("pid=%d but tid=%d", pid, tid) } } + +// Test that error values are negative. Use address 1 (a misaligned +// pointer) to get -EINVAL. +func TestMincoreErrorSign(t *testing.T) { + var dst byte + v := Mincore(unsafe.Pointer(uintptr(1)), 1, &dst) + + const EINVAL = 0x16 + if v != -EINVAL { + t.Errorf("mincore = %v, want %v", v, -EINVAL) + } +} diff --git a/src/runtime/runtime_mmap_test.go b/src/runtime/runtime_mmap_test.go new file mode 100644 index 0000000000000000000000000000000000000000..ff5e733cb016a252bb5c10c1180b54c2b98ae12e --- /dev/null +++ b/src/runtime/runtime_mmap_test.go @@ -0,0 +1,30 @@ +// Copyright 2016 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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris + +package runtime_test + +import ( + "runtime" + "runtime/internal/sys" + "testing" +) + +// Test that the error value returned by mmap is positive, as that is +// what the code in mem_bsd.go, mem_darwin.go, and mem_linux.go expects. +// See the uses of ENOMEM in sysMap in those files. +func TestMmapErrorSign(t *testing.T) { + p := runtime.Mmap(nil, ^uintptr(0)&^(sys.PhysPageSize-1), 0, runtime.MAP_ANON|runtime.MAP_PRIVATE, -1, 0) + + // The runtime.mmap function is nosplit, but t.Errorf is not. + // Reset the pointer so that we don't get an "invalid stack + // pointer" error from t.Errorf if we call it. + v := uintptr(p) + p = nil + + if v != runtime.ENOMEM { + t.Errorf("mmap = %v, want %v", v, runtime.ENOMEM) + } +} diff --git a/src/runtime/stack_test.go b/src/runtime/stack_test.go index fa073f19adb5f5e5a5f1fd1d80b82ba56ddedf37..928d1eca20a7fec865c412a4157d81a66edc79f9 100644 --- a/src/runtime/stack_test.go +++ b/src/runtime/stack_test.go @@ -111,7 +111,8 @@ GC() select { case <-done: case <-time.After(20 * time.Second): - t.Fatal("finalizer did not run") + t.Error("finalizer did not run") + return } }() wg.Wait() @@ -191,7 +192,6 @@ }() <-done }) }() - wg.Wait() } diff --git a/src/runtime/string.go b/src/runtime/string.go index f8ccd41b1d3d2cbc1121ab11eeed8a748abd7014..dd04bda04ba3cb37833d1201c3defc70ec035310 100644 --- a/src/runtime/string.go +++ b/src/runtime/string.go @@ -139,7 +139,7 @@ func stringtoslicebyte(buf *tmpBuf, s string) []byte { var b []byte if buf != nil && len(s) <= len(buf) { - b = buf[:len(s)] + b = buf[:len(s):len(s)] } else { b = rawbyteslice(len(s)) } @@ -171,7 +171,7 @@ n++ } var a []rune if buf != nil && n <= len(buf) { - a = buf[:n] + a = buf[:n:n] } else { a = rawruneslice(n) } diff --git a/src/runtime/string_test.go b/src/runtime/string_test.go index 318a5532e521c07fffe17c292ec00cdef5b9b9ac..150a25520adbc3e427ca8cb7dc68e59e1a59feb4 100644 --- a/src/runtime/string_test.go +++ b/src/runtime/string_test.go @@ -222,3 +222,18 @@ if n != 0 { t.Fatalf("want 0 allocs, got %v", n) } } + +func TestString2Slice(t *testing.T) { + // Make sure we don't return slices that expose + // an unzeroed section of stack-allocated temp buf + // between len and cap. See issue 14232. + s := "foož" + b := ([]byte)(s) + if cap(b) != 5 { + t.Errorf("want cap of 5, got %d", cap(b)) + } + r := ([]rune)(s) + if cap(r) != 4 { + t.Errorf("want cap of 4, got %d", cap(r)) + } +} diff --git a/src/runtime/sys_linux_arm64.s b/src/runtime/sys_linux_arm64.s index ca0e07aaa4cda043d976bbdc9ed6f6606f23be95..94c101a3d40cc61af4b708f7ecfb7f3847fecc36 100644 --- a/src/runtime/sys_linux_arm64.s +++ b/src/runtime/sys_linux_arm64.s @@ -269,6 +269,9 @@ MOVW off+28(FP), R5 MOVD $SYS_mmap, R8 SVC + CMN $4095, R0 + BCC 2(PC) + NEG R0,R0 MOVD R0, ret+32(FP) RET diff --git a/src/runtime/sys_linux_mips64x.s b/src/runtime/sys_linux_mips64x.s index 6ccb38f90b65affe958bbb1599a806772ce4b2a2..26437ddde4ed506faff81a35b1955630fb75d944 100644 --- a/src/runtime/sys_linux_mips64x.s +++ b/src/runtime/sys_linux_mips64x.s @@ -168,6 +168,7 @@ MOVV n+8(FP), R5 MOVV dst+16(FP), R6 MOVV $SYS_mincore, R2 SYSCALL + SUBVU R2, R0, R2 // caller expects negative errno MOVW R2, ret+24(FP) RET diff --git a/src/runtime/sys_linux_ppc64x.s b/src/runtime/sys_linux_ppc64x.s index ba410c51b64800cf4f615d19f8ec21e8d0af7722..d063e025a60ee4d32f2bbda5f2ca44ec9a7968f9 100644 --- a/src/runtime/sys_linux_ppc64x.s +++ b/src/runtime/sys_linux_ppc64x.s @@ -153,6 +153,7 @@ MOVD addr+0(FP), R3 MOVD n+8(FP), R4 MOVD dst+16(FP), R5 SYSCALL $SYS_mincore + NEG R3 // caller expects negative errno MOVW R3, ret+24(FP) RET diff --git a/src/runtime/sys_nacl_386.s b/src/runtime/sys_nacl_386.s index bf2d36ec8516c80c45f726db6870e73ec6b03352..e69a0b7bfedd343f420119fb5f659a302d7a0e5f 100644 --- a/src/runtime/sys_nacl_386.s +++ b/src/runtime/sys_nacl_386.s @@ -227,6 +227,9 @@ MOVL $0, 28(SP) LEAL 24(SP), AX MOVL AX, 20(SP) NACL_SYSCALL(SYS_mmap) + CMPL AX, $-4095 + JNA 2(PC) + NEGL AX MOVL AX, ret+24(FP) RET diff --git a/src/runtime/testdata/testprog/deadlock.go b/src/runtime/testdata/testprog/deadlock.go index 7f0a0cd1e03cac355c67b37ecbc1c1ebc837a8cc..73fbf6224dfc54fdbb66b19579d079c43d5ec9fd 100644 --- a/src/runtime/testdata/testprog/deadlock.go +++ b/src/runtime/testdata/testprog/deadlock.go @@ -29,7 +29,7 @@ register("Breakpoint", Breakpoint) register("GoexitInPanic", GoexitInPanic) register("PanicAfterGoexit", PanicAfterGoexit) register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit) - + register("PanicTraceback", PanicTraceback) } func SimpleDeadlock() { @@ -171,3 +171,21 @@ panic("hello") }() runtime.Goexit() } + +func PanicTraceback() { + pt1() +} + +func pt1() { + defer func() { + panic("panic pt1") + }() + pt2() +} + +func pt2() { + defer func() { + panic("panic pt2") + }() + panic("hello") +} diff --git a/src/runtime/time.go b/src/runtime/time.go index ffe75905263165f898030a2b8a4a7e077577dded..3f8f6968c2ab2c17f46ce5aecf3122b5b20c714d 100644 --- a/src/runtime/time.go +++ b/src/runtime/time.go @@ -16,7 +16,7 @@ type timer struct { i int // heap index // Timer wakes up at when, and then at when+period, ... (period > 0 only) - // each time calling f(now, arg) in the timer goroutine, so f must be + // each time calling f(arg, now) in the timer goroutine, so f must be // a well-behaved function and not block. when int64 period int64 diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go index 6559cd7ba3c0a0bf2fb58923024a6553582852c1..b4bfe716272929c8620704b19b890797a2005c31 100644 --- a/src/runtime/traceback.go +++ b/src/runtime/traceback.go @@ -380,7 +380,11 @@ tracepc := frame.pc // back up to CALL instruction for funcline. if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic { tracepc-- } - print(funcname(f), "(") + name := funcname(f) + if name == "runtime.gopanic" { + name = "panic" + } + print(name, "(") argp := (*[100]uintptr)(unsafe.Pointer(frame.argp)) for i := uintptr(0); i < frame.arglen/sys.PtrSize; i++ { if i >= 10 { @@ -617,10 +621,10 @@ } level, _, _ := gotraceback() name := funcname(f) - // Special case: always show runtime.panic frame, so that we can + // Special case: always show runtime.gopanic frame, so that we can // see where a panic started in the middle of a stack trace. // See golang.org/issue/5832. - if name == "runtime.panic" { + if name == "runtime.gopanic" { return true } diff --git a/test/fixedbugs/issue14331.dir/a.go b/test/fixedbugs/issue14331.dir/a.go new file mode 100644 index 0000000000000000000000000000000000000000..1b7f853bc948d41d805cb4d37ef461d74edf51cb --- /dev/null +++ b/test/fixedbugs/issue14331.dir/a.go @@ -0,0 +1,14 @@ +// Copyright 2016 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 a + +var S struct { + Str string `tag` +} + +func F() string { + v := S + return v.Str +} diff --git a/test/fixedbugs/issue14331.dir/b.go b/test/fixedbugs/issue14331.dir/b.go new file mode 100644 index 0000000000000000000000000000000000000000..7a0abb250679d462d44b49c2fd10e5ad33c086e4 --- /dev/null +++ b/test/fixedbugs/issue14331.dir/b.go @@ -0,0 +1,11 @@ +// Copyright 2016 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 b + +import "./a" + +func G() string { + return a.F() +} diff --git a/test/fixedbugs/issue14331.go b/test/fixedbugs/issue14331.go new file mode 100644 index 0000000000000000000000000000000000000000..32f3e5156c2cbcde72c464a1faa906bbf11e7df0 --- /dev/null +++ b/test/fixedbugs/issue14331.go @@ -0,0 +1,9 @@ +// compiledir + +// Copyright 2016 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. + +// Inline function misses struct tags. + +package ignored diff --git a/test/writebarrier.go b/test/writebarrier.go index 9b741a60dfc2acf63a5c1ac43d3b96155221da8a..dcd20a02252e838c709843178db7f736b83d30b4 100644 --- a/test/writebarrier.go +++ b/test/writebarrier.go @@ -144,3 +144,17 @@ func f16(x []T8, y T8) []T8 { return append(x, y) // ERROR "write barrier" } + +func t1(i interface{}) **int { + // From issue 14306, make sure we have write barriers in a type switch + // where the assigned variable escapes. + switch x := i.(type) { // ERROR "write barrier" + case *int: + return &x + } + switch y := i.(type) { // no write barrier here + case **int: + return y + } + return nil +}