Commit 43414a5d by Ian Lance Taylor

libgo: Update to final Go 1.6 release.

    
    Reviewed-on: https://go-review.googlesource.com/19592

From-SVN: r233515
parent fa837fb6
22278c6e8ce3982b09111183bc6addf0184bef1f 1c3747d20789c73447ff71cbc739f7423c4bdf67
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
036b8fd40b60830ca1d152f17148e52b96d8aa6c 7bc40ffb05d8813bf9b41a331b45d37216f9e747
The first line of this file holds the git revision number of the The first line of this file holds the git revision number of the
last merge done from the master library sources. last merge done from the master library sources.
go1.6rc1 go1.6
\ No newline at end of file \ No newline at end of file
...@@ -330,7 +330,17 @@ func readDirectoryHeader(f *File, r io.Reader) error { ...@@ -330,7 +330,17 @@ func readDirectoryHeader(f *File, r io.Reader) error {
} }
} }
if needUSize || needCSize || needHeaderOffset { // Assume that uncompressed size 2³²-1 could plausibly happen in
// an old zip32 file that was sharding inputs into the largest chunks
// possible (or is just malicious; search the web for 42.zip).
// If needUSize is true still, it means we didn't see a zip64 extension.
// As long as the compressed size is not also 2³²-1 (implausible)
// and the header is not also 2³²-1 (equally implausible),
// accept the uncompressed size 2³²-1 as valid.
// If nothing else, this keeps archive/zip working with 42.zip.
_ = needUSize
if needCSize || needHeaderOffset {
return ErrFormat return ErrFormat
} }
......
...@@ -93,7 +93,8 @@ and test commands: ...@@ -93,7 +93,8 @@ and test commands:
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
-msan -msan
enable interoperation with memory sanitizer. enable interoperation with memory sanitizer.
Supported only on linux/amd64. Supported only on linux/amd64,
and only with Clang/LLVM as the host C compiler.
-v -v
print the names of packages as they are compiled. print the names of packages as they are compiled.
-work -work
......
...@@ -72,7 +72,8 @@ and test commands: ...@@ -72,7 +72,8 @@ and test commands:
Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64. Supported only on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64.
-msan -msan
enable interoperation with memory sanitizer. enable interoperation with memory sanitizer.
Supported only on linux/amd64. Supported only on linux/amd64,
and only with Clang/LLVM as the host C compiler.
-v -v
print the names of packages as they are compiled. print the names of packages as they are compiled.
-work -work
...@@ -674,6 +675,7 @@ var ( ...@@ -674,6 +675,7 @@ var (
goarch string goarch string
goos string goos string
exeSuffix string exeSuffix string
gopath []string
) )
func init() { func init() {
...@@ -682,6 +684,7 @@ func init() { ...@@ -682,6 +684,7 @@ func init() {
if goos == "windows" { if goos == "windows" {
exeSuffix = ".exe" exeSuffix = ".exe"
} }
gopath = filepath.SplitList(buildContext.GOPATH)
} }
// A builder holds global state about a build. // A builder holds global state about a build.
...@@ -1694,6 +1697,22 @@ func (b *builder) includeArgs(flag string, all []*action) []string { ...@@ -1694,6 +1697,22 @@ func (b *builder) includeArgs(flag string, all []*action) []string {
inc = append(inc, flag, b.work) inc = append(inc, flag, b.work)
// Finally, look in the installed package directories for each action. // 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 { for _, a1 := range all {
if a1.p == nil { if a1.p == nil {
continue continue
......
...@@ -454,7 +454,9 @@ func envForDir(dir string, base []string) []string { ...@@ -454,7 +454,9 @@ func envForDir(dir string, base []string) []string {
// mergeEnvLists merges the two environment lists such that // mergeEnvLists merges the two environment lists such that
// variables with the same name in "in" replace those in "out". // variables with the same name in "in" replace those in "out".
// This always returns a newly allocated slice.
func mergeEnvLists(in, out []string) []string { func mergeEnvLists(in, out []string) []string {
out = append([]string(nil), out...)
NextVar: NextVar:
for _, inkv := range in { for _, inkv := range in {
k := strings.SplitAfterN(inkv, "=", 2)[0] k := strings.SplitAfterN(inkv, "=", 2)[0]
...@@ -524,6 +526,15 @@ func hasFilePathPrefix(s, prefix string) bool { ...@@ -524,6 +526,15 @@ func hasFilePathPrefix(s, prefix string) bool {
} }
} }
// expandPath returns the symlink-expanded form of path.
func expandPath(p string) string {
x, err := filepath.EvalSymlinks(p)
if err == nil {
return x
}
return p
}
// treeCanMatchPattern(pattern)(name) reports whether // treeCanMatchPattern(pattern)(name) reports whether
// name or children of name can possibly match pattern. // name or children of name can possibly match pattern.
// Pattern is the same limited glob accepted by matchPattern. // Pattern is the same limited glob accepted by matchPattern.
......
...@@ -419,11 +419,18 @@ func vendoredImportPath(parent *Package, path string) (found string) { ...@@ -419,11 +419,18 @@ func vendoredImportPath(parent *Package, path string) (found string) {
if parent == nil || parent.Root == "" || !go15VendorExperiment { if parent == nil || parent.Root == "" || !go15VendorExperiment {
return path return path
} }
dir := filepath.Clean(parent.Dir) dir := filepath.Clean(parent.Dir)
root := filepath.Join(parent.Root, "src") root := filepath.Join(parent.Root, "src")
if !hasFilePathPrefix(dir, root) {
// Look for symlinks before reporting error.
dir = expandPath(dir)
root = expandPath(root)
}
if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator { if !hasFilePathPrefix(dir, root) || len(dir) <= len(root) || dir[len(root)] != filepath.Separator {
fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator)) fatalf("invalid vendoredImportPath: dir=%q root=%q separator=%q", dir, root, string(filepath.Separator))
} }
vpath := "vendor/" + path vpath := "vendor/" + path
for i := len(dir); i >= len(root); i-- { for i := len(dir); i >= len(root); i-- {
if i < len(dir) && dir[i] != filepath.Separator { if i < len(dir) && dir[i] != filepath.Separator {
...@@ -537,6 +544,13 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package { ...@@ -537,6 +544,13 @@ func disallowInternal(srcDir string, p *Package, stk *importStack) *Package {
return p return p
} }
// Look for symlinks before reporting error.
srcDir = expandPath(srcDir)
parent = expandPath(parent)
if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
return p
}
// Internal is present, and srcDir is outside parent's tree. Not allowed. // Internal is present, and srcDir is outside parent's tree. Not allowed.
perr := *p perr := *p
perr.Error = &PackageError{ perr.Error = &PackageError{
...@@ -634,6 +648,13 @@ func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Pack ...@@ -634,6 +648,13 @@ func disallowVendorVisibility(srcDir string, p *Package, stk *importStack) *Pack
return p return p
} }
// Look for symlinks before reporting error.
srcDir = expandPath(srcDir)
parent = expandPath(parent)
if hasFilePathPrefix(filepath.Clean(srcDir), filepath.Clean(parent)) {
return p
}
// Vendor is present, and srcDir is outside parent's tree. Not allowed. // Vendor is present, and srcDir is outside parent's tree. Not allowed.
perr := *p perr := *p
perr.Error = &PackageError{ perr.Error = &PackageError{
...@@ -957,7 +978,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package ...@@ -957,7 +978,7 @@ func (p *Package) load(stk *importStack, bp *build.Package, err error) *Package
} }
} }
} }
if p.Standard && !p1.Standard && p.Error == nil { if p.Standard && p.Error == nil && !p1.Standard && p1.Error == nil {
p.Error = &PackageError{ p.Error = &PackageError{
ImportStack: stk.copy(), ImportStack: stk.copy(),
Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath), Err: fmt.Sprintf("non-standard import %q in standard package %q", path, p.ImportPath),
...@@ -1532,11 +1553,14 @@ func computeBuildID(p *Package) { ...@@ -1532,11 +1553,14 @@ func computeBuildID(p *Package) {
fmt.Fprintf(h, "file %s\n", file) fmt.Fprintf(h, "file %s\n", file)
} }
// Include the content of runtime/zversion.go in the hash // Include the content of runtime/internal/sys/zversion.go in the hash
// for package runtime. This will give package runtime a // for package runtime. This will give package runtime a
// different build ID in each Go release. // different build ID in each Go release.
if p.Standard && p.ImportPath == "runtime" { if p.Standard && p.ImportPath == "runtime/internal/sys" {
data, _ := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go")) data, err := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go"))
if err != nil {
fatalf("go: %s", err)
}
fmt.Fprintf(h, "zversion %q\n", string(data)) fmt.Fprintf(h, "zversion %q\n", string(data))
} }
......
...@@ -122,7 +122,7 @@ var vcsGit = &vcsCmd{ ...@@ -122,7 +122,7 @@ var vcsGit = &vcsCmd{
name: "Git", name: "Git",
cmd: "git", cmd: "git",
createCmd: []string{"clone {repo} {dir}", "-C {dir} submodule update --init --recursive"}, createCmd: []string{"clone {repo} {dir}", "-go-internal-cd {dir} submodule update --init --recursive"},
downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"}, downloadCmd: []string{"pull --ff-only", "submodule update --init --recursive"},
tagCmd: []tagCmd{ tagCmd: []tagCmd{
...@@ -335,6 +335,15 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool) ...@@ -335,6 +335,15 @@ func (v *vcsCmd) run1(dir string, cmdline string, keyval []string, verbose bool)
args[i] = expand(m, arg) args[i] = expand(m, arg)
} }
if len(args) >= 2 && args[0] == "-go-internal-cd" {
if filepath.IsAbs(args[1]) {
dir = args[1]
} else {
dir = filepath.Join(dir, args[1])
}
args = args[2:]
}
_, err := exec.LookPath(v.cmd) _, err := exec.LookPath(v.cmd)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, fmt.Fprintf(os.Stderr,
......
...@@ -96,7 +96,7 @@ func (x stringVal) String() string { ...@@ -96,7 +96,7 @@ func (x stringVal) String() string {
// only the first maxLen-3 runes; then add "...". // only the first maxLen-3 runes; then add "...".
i := 0 i := 0
for n := 0; n < maxLen-3; n++ { for n := 0; n < maxLen-3; n++ {
_, size := utf8.DecodeRuneInString(s) _, size := utf8.DecodeRuneInString(s[i:])
i += size i += size
} }
s = s[:i] + "..." s = s[:i] + "..."
......
...@@ -204,6 +204,7 @@ func eql(x, y Value) bool { ...@@ -204,6 +204,7 @@ func eql(x, y Value) bool {
// String tests // String tests
var xxx = strings.Repeat("x", 68) var xxx = strings.Repeat("x", 68)
var issue14262 = `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة التي تحددها المؤلف أو المرخص (ولكن ليس بأي حال من الأحوال أن توحي وتقترح بتحول أو استخدامك للعمل). المشاركة على قدم المساواة — إذا كنت يعدل ، والتغيير ، أو الاستفادة من هذا العمل ، قد ينتج عن توزيع العمل إلا في ظل تشابه او تطابق فى واحد لهذا الترخيص."`
var stringTests = []struct { var stringTests = []struct {
input, short, exact string input, short, exact string
...@@ -225,6 +226,7 @@ var stringTests = []struct { ...@@ -225,6 +226,7 @@ var stringTests = []struct {
{`"` + xxx + `xx"`, `"` + xxx + `xx"`, `"` + xxx + `xx"`}, {`"` + xxx + `xx"`, `"` + xxx + `xx"`, `"` + xxx + `xx"`},
{`"` + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + `xxx"`}, {`"` + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + `xxx"`},
{`"` + xxx + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + xxx + `xxx"`}, {`"` + xxx + xxx + `xxx"`, `"` + xxx + `...`, `"` + xxx + xxx + `xxx"`},
{issue14262, `"بموجب الشروط التالية نسب المصنف — يجب عليك أن تنسب العمل بالطريقة ال...`, issue14262},
// Int // Int
{"0", "0", "0"}, {"0", "0", "0"},
......
...@@ -31,7 +31,8 @@ var pkgExts = [...]string{".a", ".o"} ...@@ -31,7 +31,8 @@ var pkgExts = [...]string{".a", ".o"}
// FindPkg returns the filename and unique package id for an import // FindPkg returns the filename and unique package id for an import
// path based on package information provided by build.Import (using // 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. // If no file was found, an empty filename is returned.
// //
func FindPkg(path, srcDir string) (filename, id string) { func FindPkg(path, srcDir string) (filename, id string) {
...@@ -44,6 +45,9 @@ func FindPkg(path, srcDir string) (filename, id string) { ...@@ -44,6 +45,9 @@ func FindPkg(path, srcDir string) (filename, id string) {
default: default:
// "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x" // "x" -> "$GOPATH/pkg/$GOOS_$GOARCH/x.ext", "x"
// Don't require the source files to be present. // 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) bp, _ := build.Import(path, srcDir, build.FindOnly|build.AllowBinary)
if bp.PkgObj == "" { if bp.PkgObj == "" {
return return
......
...@@ -184,7 +184,8 @@ func roundFloat64(x constant.Value) constant.Value { ...@@ -184,7 +184,8 @@ func roundFloat64(x constant.Value) constant.Value {
// provided (only needed for int/uint sizes). // provided (only needed for int/uint sizes).
// //
// If rounded != nil, *rounded is set to the rounded value of x for // 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. // 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 { func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *constant.Value) bool {
if x.Kind() == constant.Unknown { if x.Kind() == constant.Unknown {
...@@ -197,6 +198,9 @@ func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *con ...@@ -197,6 +198,9 @@ func representableConst(x constant.Value, conf *Config, typ *Basic, rounded *con
if x.Kind() != constant.Int { if x.Kind() != constant.Int {
return false return false
} }
if rounded != nil {
*rounded = x
}
if x, ok := constant.Int64Val(x); ok { if x, ok := constant.Int64Val(x); ok {
switch typ.kind { switch typ.kind {
case Int: case Int:
...@@ -808,8 +812,6 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o ...@@ -808,8 +812,6 @@ func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, o
typ := x.typ.Underlying().(*Basic) typ := x.typ.Underlying().(*Basic)
// force integer division of integer operands // force integer division of integer operands
if op == token.QUO && isInteger(typ) { if op == token.QUO && isInteger(typ) {
xval = constant.ToInt(xval)
yval = constant.ToInt(yval)
op = token.QUO_ASSIGN op = token.QUO_ASSIGN
} }
x.val = constant.BinaryOp(xval, op, yval) x.val = constant.BinaryOp(xval, op, yval)
......
...@@ -483,11 +483,9 @@ func pkgName(path string) string { ...@@ -483,11 +483,9 @@ func pkgName(path string) string {
// (Per the go/build package dependency tests, we cannot import // (Per the go/build package dependency tests, we cannot import
// path/filepath and simply use filepath.Dir.) // path/filepath and simply use filepath.Dir.)
func dir(path string) string { func dir(path string) string {
if i := strings.LastIndexAny(path, "/\\"); i >= 0 { if i := strings.LastIndexAny(path, `/\`); i > 0 {
path = path[:i] return path[:i]
} }
if path == "" { // i <= 0
path = "." return "."
}
return path
} }
...@@ -1001,9 +1001,11 @@ func TestTransportDiscardsUnneededConns(t *testing.T) { ...@@ -1001,9 +1001,11 @@ func TestTransportDiscardsUnneededConns(t *testing.T) {
} }
// tests that Transport doesn't retain a pointer to the provided request. // tests that Transport doesn't retain a pointer to the provided request.
func TestTransportGCRequest_h1(t *testing.T) { testTransportGCRequest(t, h1Mode) } func TestTransportGCRequest_Body_h1(t *testing.T) { testTransportGCRequest(t, h1Mode, true) }
func TestTransportGCRequest_h2(t *testing.T) { testTransportGCRequest(t, h2Mode) } func TestTransportGCRequest_Body_h2(t *testing.T) { testTransportGCRequest(t, h2Mode, true) }
func testTransportGCRequest(t *testing.T, h2 bool) { func TestTransportGCRequest_NoBody_h1(t *testing.T) { testTransportGCRequest(t, h1Mode, false) }
func TestTransportGCRequest_NoBody_h2(t *testing.T) { testTransportGCRequest(t, h2Mode, false) }
func testTransportGCRequest(t *testing.T, h2, body bool) {
if runtime.Compiler == "gccgo" { if runtime.Compiler == "gccgo" {
t.Skip("skipping on gccgo because conservative GC means that finalizer may never run") t.Skip("skipping on gccgo because conservative GC means that finalizer may never run")
} }
...@@ -1011,7 +1013,9 @@ func testTransportGCRequest(t *testing.T, h2 bool) { ...@@ -1011,7 +1013,9 @@ func testTransportGCRequest(t *testing.T, h2 bool) {
defer afterTest(t) defer afterTest(t)
cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) { cst := newClientServerTest(t, h2, HandlerFunc(func(w ResponseWriter, r *Request) {
ioutil.ReadAll(r.Body) ioutil.ReadAll(r.Body)
io.WriteString(w, "Hello.") if body {
io.WriteString(w, "Hello.")
}
})) }))
defer cst.close() defer cst.close()
......
...@@ -202,10 +202,31 @@ func (s *Server) logCloseHangDebugInfo() { ...@@ -202,10 +202,31 @@ func (s *Server) logCloseHangDebugInfo() {
// CloseClientConnections closes any open HTTP connections to the test Server. // CloseClientConnections closes any open HTTP connections to the test Server.
func (s *Server) CloseClientConnections() { func (s *Server) CloseClientConnections() {
var conns int
ch := make(chan bool)
s.mu.Lock() s.mu.Lock()
defer s.mu.Unlock()
for c := range s.conns { 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 @@ func (s *Server) wrap() { ...@@ -267,9 +288,13 @@ func (s *Server) wrap() {
} }
} }
// closeConn closes c. Except on plan9, which is special. See comment below. // closeConn closes c.
// s.mu must be held. // 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" { if runtime.GOOS == "plan9" {
// Go's Plan 9 net package isn't great at unblocking reads when // Go's Plan 9 net package isn't great at unblocking reads when
// their underlying TCP connections are closed. Don't trust // their underlying TCP connections are closed. Don't trust
...@@ -278,7 +303,21 @@ func (s *Server) closeConn(c net.Conn) { ...@@ -278,7 +303,21 @@ func (s *Server) closeConn(c net.Conn) {
// resources if the syscall doesn't end up returning. Oh well. // resources if the syscall doesn't end up returning. Oh well.
s.forgetConn(c) 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 // forgetConn removes c from the set of tracked conns and decrements it from the
......
...@@ -84,3 +84,17 @@ func TestServerCloseBlocking(t *testing.T) { ...@@ -84,3 +84,17 @@ func TestServerCloseBlocking(t *testing.T) {
ts.Close() // test we don't hang here forever. 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)
}
}
...@@ -106,11 +106,12 @@ func copyHeader(dst, src http.Header) { ...@@ -106,11 +106,12 @@ func copyHeader(dst, src http.Header) {
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
var hopHeaders = []string{ var hopHeaders = []string{
"Connection", "Connection",
"Proxy-Connection", // non-standard but still sent by libcurl and rejected by e.g. google
"Keep-Alive", "Keep-Alive",
"Proxy-Authenticate", "Proxy-Authenticate",
"Proxy-Authorization", "Proxy-Authorization",
"Te", // canonicalized version of "TE" "Te", // canonicalized version of "TE"
"Trailers", "Trailer", // not Trailers per URL above; http://www.rfc-editor.org/errata_search.php?eid=4522
"Transfer-Encoding", "Transfer-Encoding",
"Upgrade", "Upgrade",
} }
......
...@@ -45,9 +45,13 @@ func TestReverseProxy(t *testing.T) { ...@@ -45,9 +45,13 @@ func TestReverseProxy(t *testing.T) {
if c := r.Header.Get("Upgrade"); c != "" { if c := r.Header.Get("Upgrade"); c != "" {
t.Errorf("handler got Upgrade header value %q", c) t.Errorf("handler got Upgrade header value %q", c)
} }
if c := r.Header.Get("Proxy-Connection"); c != "" {
t.Errorf("handler got Proxy-Connection header value %q", c)
}
if g, e := r.Host, "some-name"; g != e { if g, e := r.Host, "some-name"; g != e {
t.Errorf("backend got Host header %q, want %q", g, e) t.Errorf("backend got Host header %q, want %q", g, e)
} }
w.Header().Set("Trailers", "not a special header field name")
w.Header().Set("Trailer", "X-Trailer") w.Header().Set("Trailer", "X-Trailer")
w.Header().Set("X-Foo", "bar") w.Header().Set("X-Foo", "bar")
w.Header().Set("Upgrade", "foo") w.Header().Set("Upgrade", "foo")
...@@ -71,6 +75,7 @@ func TestReverseProxy(t *testing.T) { ...@@ -71,6 +75,7 @@ func TestReverseProxy(t *testing.T) {
getReq, _ := http.NewRequest("GET", frontend.URL, nil) getReq, _ := http.NewRequest("GET", frontend.URL, nil)
getReq.Host = "some-name" getReq.Host = "some-name"
getReq.Header.Set("Connection", "close") getReq.Header.Set("Connection", "close")
getReq.Header.Set("Proxy-Connection", "should be deleted")
getReq.Header.Set("Upgrade", "foo") getReq.Header.Set("Upgrade", "foo")
getReq.Close = true getReq.Close = true
res, err := http.DefaultClient.Do(getReq) res, err := http.DefaultClient.Do(getReq)
...@@ -86,6 +91,9 @@ func TestReverseProxy(t *testing.T) { ...@@ -86,6 +91,9 @@ func TestReverseProxy(t *testing.T) {
if c := res.Header.Get(fakeHopHeader); c != "" { if c := res.Header.Get(fakeHopHeader); c != "" {
t.Errorf("got %s header value %q", fakeHopHeader, c) t.Errorf("got %s header value %q", fakeHopHeader, c)
} }
if g, e := res.Header.Get("Trailers"), "not a special header field name"; g != e {
t.Errorf("header Trailers = %q; want %q", g, e)
}
if g, e := len(res.Header["X-Multi-Value"]), 2; g != e { if g, e := len(res.Header["X-Multi-Value"]), 2; g != e {
t.Errorf("got %d X-Multi-Value header values; expected %d", g, e) t.Errorf("got %d X-Multi-Value header values; expected %d", g, e)
} }
......
...@@ -99,30 +99,37 @@ type Request struct { ...@@ -99,30 +99,37 @@ type Request struct {
ProtoMajor int // 1 ProtoMajor int // 1
ProtoMinor int // 0 ProtoMinor int // 0
// A header maps request lines to their values. // Header contains the request header fields either received
// If the header says // 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-encoding: gzip, deflate
// Accept-Language: en-us // Accept-Language: en-us
// Connection: keep-alive // fOO: Bar
// foo: two
// //
// then // then
// //
// Header = map[string][]string{ // Header = map[string][]string{
// "Accept-Encoding": {"gzip, deflate"}, // "Accept-Encoding": {"gzip, deflate"},
// "Accept-Language": {"en-us"}, // "Accept-Language": {"en-us"},
// "Connection": {"keep-alive"}, // "Foo": {"Bar", "two"},
// } // }
// //
// HTTP defines that header names are case-insensitive. // For incoming requests, the Host header is promoted to the
// The request parser implements this by canonicalizing the // Request.Host field and removed from the Header map.
// name, making the first character and any characters
// following a hyphen uppercase and the rest lowercase.
// //
// For client requests certain headers are automatically // HTTP defines that header names are case-insensitive. The
// added and may override values in Header. // 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 Header Header
// Body is the request's body. // Body is the request's body.
...@@ -152,8 +159,15 @@ type Request struct { ...@@ -152,8 +159,15 @@ type Request struct {
TransferEncoding []string TransferEncoding []string
// Close indicates whether to close the connection after // Close indicates whether to close the connection after
// replying to this request (for servers) or after sending // replying to this request (for servers) or after sending this
// the request (for clients). // 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 Close bool
// For server requests Host specifies the host on which the // For server requests Host specifies the host on which the
......
...@@ -1039,12 +1039,30 @@ func TestAutomaticHTTP2_Serve(t *testing.T) { ...@@ -1039,12 +1039,30 @@ func TestAutomaticHTTP2_Serve(t *testing.T) {
} }
func TestAutomaticHTTP2_ListenAndServe(t *testing.T) { func TestAutomaticHTTP2_ListenAndServe(t *testing.T) {
defer afterTest(t)
defer SetTestHookServerServe(nil)
cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey) cert, err := tls.X509KeyPair(internal.LocalhostCert, internal.LocalhostKey)
if err != nil { if err != nil {
t.Fatal(err) 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 ok bool
var s *Server var s *Server
const maxTries = 5 const maxTries = 5
...@@ -1060,10 +1078,8 @@ Try: ...@@ -1060,10 +1078,8 @@ Try:
lnc <- ln lnc <- ln
}) })
s = &Server{ s = &Server{
Addr: addr, Addr: addr,
TLSConfig: &tls.Config{ TLSConfig: tlsConf,
Certificates: []tls.Certificate{cert},
},
} }
errc := make(chan error, 1) errc := make(chan error, 1)
go func() { errc <- s.ListenAndServeTLS("", "") }() go func() { errc <- s.ListenAndServeTLS("", "") }()
...@@ -2416,7 +2432,7 @@ func TestCloseNotifierPipelined(t *testing.T) { ...@@ -2416,7 +2432,7 @@ func TestCloseNotifierPipelined(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("error dialing: %v", err) t.Fatalf("error dialing: %v", err)
} }
diec := make(chan bool, 2) diec := make(chan bool, 1)
go func() { go func() {
const req = "GET / HTTP/1.1\r\nConnection: keep-alive\r\nHost: foo\r\n\r\n" 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 _, err = io.WriteString(conn, req+req) // two requests
...@@ -2426,13 +2442,23 @@ func TestCloseNotifierPipelined(t *testing.T) { ...@@ -2426,13 +2442,23 @@ func TestCloseNotifierPipelined(t *testing.T) {
<-diec <-diec
conn.Close() conn.Close()
}() }()
reqs := 0
closes := 0
For: For:
for { for {
select { select {
case <-gotReq: case <-gotReq:
diec <- true reqs++
if reqs > 2 {
t.Fatal("too many requests")
} else if reqs > 1 {
diec <- true
}
case <-sawClose: case <-sawClose:
break For closes++
if closes > 1 {
break For
}
case <-time.After(5 * time.Second): case <-time.After(5 * time.Second):
ts.CloseClientConnections() ts.CloseClientConnections()
t.Fatal("timeout") t.Fatal("timeout")
......
...@@ -2233,10 +2233,11 @@ func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error { ...@@ -2233,10 +2233,11 @@ func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
// Accepted connections are configured to enable TCP keep-alives. // Accepted connections are configured to enable TCP keep-alives.
// //
// Filenames containing a certificate and matching private key for the // Filenames containing a certificate and matching private key for the
// server must be provided if the Server's TLSConfig.Certificates is // server must be provided if neither the Server's TLSConfig.Certificates
// not populated. If the certificate is signed by a certificate // nor TLSConfig.GetCertificate are populated. If the certificate is
// authority, the certFile should be the concatenation of the server's // signed by a certificate authority, the certFile should be the
// certificate, any intermediates, and the CA's certificate. // concatenation of the server's certificate, any intermediates, and
// the CA's certificate.
// //
// If srv.Addr is blank, ":https" is used. // If srv.Addr is blank, ":https" is used.
// //
...@@ -2258,7 +2259,8 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error { ...@@ -2258,7 +2259,8 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
config.NextProtos = append(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 var err error
config.Certificates = make([]tls.Certificate, 1) config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile) config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
......
...@@ -163,6 +163,22 @@ func (t *Transport) onceSetNextProtoDefaults() { ...@@ -163,6 +163,22 @@ func (t *Transport) onceSetNextProtoDefaults() {
return return
} }
if t.TLSNextProto != nil { 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 return
} }
t2, err := http2configureTransport(t) t2, err := http2configureTransport(t)
......
...@@ -2208,9 +2208,8 @@ func TestTransportTLSHandshakeTimeout(t *testing.T) { ...@@ -2208,9 +2208,8 @@ func TestTransportTLSHandshakeTimeout(t *testing.T) {
// Trying to repro golang.org/issue/3514 // Trying to repro golang.org/issue/3514
func TestTLSServerClosesConnection(t *testing.T) { func TestTLSServerClosesConnection(t *testing.T) {
defer afterTest(t) defer afterTest(t)
if runtime.GOOS == "windows" { setFlaky(t, 7634)
t.Skip("skipping flaky test on Windows; golang.org/issue/7634")
}
closedc := make(chan bool, 1) closedc := make(chan bool, 1)
ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) { ts := httptest.NewTLSServer(HandlerFunc(func(w ResponseWriter, r *Request) {
if strings.Contains(r.URL.Path, "/keep-alive-then-die") { if strings.Contains(r.URL.Path, "/keep-alive-then-die") {
...@@ -2886,23 +2885,34 @@ func TestTransportPrefersResponseOverWriteError(t *testing.T) { ...@@ -2886,23 +2885,34 @@ func TestTransportPrefersResponseOverWriteError(t *testing.T) {
} }
func TestTransportAutomaticHTTP2(t *testing.T) { func TestTransportAutomaticHTTP2(t *testing.T) {
tr := &Transport{} testTransportAutoHTTP(t, &Transport{}, true)
_, err := tr.RoundTrip(new(Request)) }
if err == nil {
t.Error("expected error from RoundTrip") func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) {
} testTransportAutoHTTP(t, &Transport{
if tr.TLSNextProto["h2"] == nil { TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper),
t.Errorf("HTTP/2 not registered.") }, 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: func testTransportAutoHTTP(t *testing.T, tr *Transport, wantH2 bool) {
tr = &Transport{TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper)} _, err := tr.RoundTrip(new(Request))
_, err = tr.RoundTrip(new(Request))
if err == nil { if err == nil {
t.Error("expected error from RoundTrip") t.Error("expected error from RoundTrip")
} }
if tr.TLSNextProto["h2"] != nil { if reg := tr.TLSNextProto["h2"] != nil; reg != wantH2 {
t.Errorf("HTTP/2 registered, despite non-nil TLSNextProto field") t.Errorf("HTTP/2 registered = %v; want %v", reg, wantH2)
} }
} }
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
"os" "os"
"runtime" "runtime"
"testing" "testing"
"time"
) )
func TestCloseRead(t *testing.T) { func TestCloseRead(t *testing.T) {
...@@ -209,6 +210,7 @@ func TestListenerClose(t *testing.T) { ...@@ -209,6 +210,7 @@ func TestListenerClose(t *testing.T) {
defer os.Remove(ln.Addr().String()) defer os.Remove(ln.Addr().String())
} }
dst := ln.Addr().String()
if err := ln.Close(); err != nil { if err := ln.Close(); err != nil {
if perr := parseCloseError(err); perr != nil { if perr := parseCloseError(err); perr != nil {
t.Error(perr) t.Error(perr)
...@@ -222,9 +224,24 @@ func TestListenerClose(t *testing.T) { ...@@ -222,9 +224,24 @@ func TestListenerClose(t *testing.T) {
} }
if network == "tcp" { if network == "tcp" {
cc, err := Dial("tcp", ln.Addr().String()) // We will have two TCP FSMs inside the
// kernel here. There's no guarantee that a
// signal comes from the far end FSM will be
// delivered immediately to the near end FSM,
// especially on the platforms that allow
// multiple consumer threads to pull pending
// established connections at the same time by
// enabling SO_REUSEPORT option such as Linux,
// DragonFly BSD. So we need to give some time
// quantum to the kernel.
//
// Note that net.inet.tcp.reuseport_ext=1 by
// default on DragonFly BSD.
time.Sleep(time.Millisecond)
cc, err := Dial("tcp", dst)
if err == nil { if err == nil {
t.Error("Dial to closed TCP listener succeeeded.") t.Error("Dial to closed TCP listener succeeded.")
cc.Close() cc.Close()
} }
} }
...@@ -272,6 +289,9 @@ func TestListenCloseListen(t *testing.T) { ...@@ -272,6 +289,9 @@ func TestListenCloseListen(t *testing.T) {
} }
addr := ln.Addr().String() addr := ln.Addr().String()
if err := ln.Close(); err != nil { if err := ln.Close(); err != nil {
if perr := parseCloseError(err); perr != nil {
t.Error(perr)
}
t.Fatal(err) t.Fatal(err)
} }
ln, err = Listen("tcp", addr) ln, err = Listen("tcp", addr)
......
...@@ -7,9 +7,13 @@ package os ...@@ -7,9 +7,13 @@ package os
import "time" import "time"
// FindProcess looks for a running process by its pid. // FindProcess looks for a running process by its pid.
//
// The Process it returns can be used to obtain information // The Process it returns can be used to obtain information
// about the underlying operating system process. // about the underlying operating system process.
func FindProcess(pid int) (p *Process, err error) { //
// On Unix systems, FindProcess always succeeds and returns a Process
// for the given pid, regardless of whether the process exists.
func FindProcess(pid int) (*Process, error) {
return findProcess(pid) return findProcess(pid)
} }
......
...@@ -15,12 +15,19 @@ import "unsafe" ...@@ -15,12 +15,19 @@ import "unsafe"
//go:linkname _cgo_mmap _cgo_mmap //go:linkname _cgo_mmap _cgo_mmap
var _cgo_mmap unsafe.Pointer var _cgo_mmap unsafe.Pointer
func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) (ret unsafe.Pointer) { func mmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer {
if _cgo_mmap != nil { if _cgo_mmap != nil {
// Make ret a uintptr so that writing to it in the
// function literal does not trigger a write barrier.
// A write barrier here could break because of the way
// that mmap uses the same value both as a pointer and
// an errno value.
// TODO: Fix mmap to return two values.
var ret uintptr
systemstack(func() { systemstack(func() {
ret = callCgoMmap(addr, n, prot, flags, fd, off) ret = callCgoMmap(addr, n, prot, flags, fd, off)
}) })
return return unsafe.Pointer(ret)
} }
return sysMmap(addr, n, prot, flags, fd, off) return sysMmap(addr, n, prot, flags, fd, off)
} }
...@@ -31,4 +38,4 @@ func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) ...@@ -31,4 +38,4 @@ func sysMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32)
// cgoMmap calls the mmap function in the runtime/cgo package on the // cgoMmap calls the mmap function in the runtime/cgo package on the
// callCgoMmap calls the mmap function in the runtime/cgo package // callCgoMmap calls the mmap function in the runtime/cgo package
// using the GCC calling convention. It is implemented in assembly. // using the GCC calling convention. It is implemented in assembly.
func callCgoMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) unsafe.Pointer func callCgoMmap(addr unsafe.Pointer, n uintptr, prot, flags, fd int32, off uint32) uintptr
...@@ -135,9 +135,6 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) { ...@@ -135,9 +135,6 @@ func cgoCheckTypedBlock(typ *_type, src unsafe.Pointer, off, size uintptr) {
hbits := heapBitsForAddr(uintptr(src)) hbits := heapBitsForAddr(uintptr(src))
for i := uintptr(0); i < off+size; i += sys.PtrSize { for i := uintptr(0); i < off+size; i += sys.PtrSize {
bits := hbits.bits() bits := hbits.bits()
if bits != 0 {
println(i, bits)
}
if i >= off && bits&bitPointer != 0 { if i >= off && bits&bitPointer != 0 {
v := *(*unsafe.Pointer)(add(src, i)) v := *(*unsafe.Pointer)(add(src, i))
if cgoIsGoPointer(v) { if cgoIsGoPointer(v) {
......
...@@ -317,3 +317,22 @@ func TestNetpollDeadlock(t *testing.T) { ...@@ -317,3 +317,22 @@ func TestNetpollDeadlock(t *testing.T) {
t.Fatalf("output does not start with %q:\n%s", want, output) 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]:]
}
}
...@@ -14,6 +14,7 @@ import ( ...@@ -14,6 +14,7 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings"
"syscall" "syscall"
"testing" "testing"
) )
...@@ -52,6 +53,18 @@ func TestCrashDumpsAllThreads(t *testing.T) { ...@@ -52,6 +53,18 @@ func TestCrashDumpsAllThreads(t *testing.T) {
cmd = exec.Command(filepath.Join(dir, "a.exe")) cmd = exec.Command(filepath.Join(dir, "a.exe"))
cmd = testEnv(cmd) cmd = testEnv(cmd)
cmd.Env = append(cmd.Env, "GOTRACEBACK=crash") 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 var outbuf bytes.Buffer
cmd.Stdout = &outbuf cmd.Stdout = &outbuf
cmd.Stderr = &outbuf cmd.Stderr = &outbuf
...@@ -137,8 +150,8 @@ func loop(i int, c chan bool) { ...@@ -137,8 +150,8 @@ func loop(i int, c chan bool) {
func TestSignalExitStatus(t *testing.T) { func TestSignalExitStatus(t *testing.T) {
testenv.MustHaveGoBuild(t) testenv.MustHaveGoBuild(t)
switch runtime.GOOS { switch runtime.GOOS {
case "netbsd": case "netbsd", "solaris":
t.Skip("skipping on NetBSD; see https://golang.org/issue/14063") t.Skipf("skipping on %s; see https://golang.org/issue/14063", runtime.GOOS)
} }
exe, err := buildTestProg(t, "testprog") exe, err := buildTestProg(t, "testprog")
if err != nil { if err != nil {
......
...@@ -7,3 +7,4 @@ ...@@ -7,3 +7,4 @@
package runtime package runtime
//var NewOSProc0 = newosproc0 //var NewOSProc0 = newosproc0
//var Mincore = mincore
// 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 ignore
// Export guts for testing.
package runtime
var Mmap = mmap
const ENOMEM = _ENOMEM
const MAP_ANON = _MAP_ANON
const MAP_PRIVATE = _MAP_PRIVATE
...@@ -351,7 +351,7 @@ func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) { ...@@ -351,7 +351,7 @@ func printStackRecord(w io.Writer, stk []uintptr, allFrames bool) {
name := f.Name() name := f.Name()
// Hide runtime.goexit and any runtime functions at the beginning. // Hide runtime.goexit and any runtime functions at the beginning.
// This is useful mainly for allocation traces. // This is useful mainly for allocation traces.
wasPanic = name == "runtime.panic" wasPanic = name == "runtime.gopanic"
if name == "runtime.goexit" || !show && (strings.HasPrefix(name, "runtime.") || strings.HasPrefix(name, "runtime_")) { if name == "runtime.goexit" || !show && (strings.HasPrefix(name, "runtime.") || strings.HasPrefix(name, "runtime_")) {
continue continue
} }
......
...@@ -96,7 +96,7 @@ func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) { ...@@ -96,7 +96,7 @@ func parseProfile(t *testing.T, bytes []byte, f func(uintptr, []uintptr)) {
if l < 5+3 { if l < 5+3 {
t.Logf("profile too short: %#x", val) t.Logf("profile too short: %#x", val)
if badOS[runtime.GOOS] { if badOS[runtime.GOOS] {
t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS) t.Skipf("ignoring failure on %s; see golang.org/issue/13841", runtime.GOOS)
return return
} }
t.FailNow() t.FailNow()
...@@ -171,7 +171,7 @@ func testCPUProfile(t *testing.T, need []string, f func(dur time.Duration)) { ...@@ -171,7 +171,7 @@ func testCPUProfile(t *testing.T, need []string, f func(dur time.Duration)) {
} }
if badOS[runtime.GOOS] { if badOS[runtime.GOOS] {
t.Skipf("ignoring failure on %s; see golang.org/issue/6047", runtime.GOOS) t.Skipf("ignoring failure on %s; see golang.org/issue/13841", runtime.GOOS)
return return
} }
// Ignore the failure if the tests are running in a QEMU-based emulator, // Ignore the failure if the tests are running in a QEMU-based emulator,
...@@ -421,11 +421,13 @@ func deepStack(depth int) int { ...@@ -421,11 +421,13 @@ func deepStack(depth int) int {
return deepStack(depth-1) + 1 return deepStack(depth-1) + 1
} }
// Operating systems that are expected to fail the tests. See issue 6047. // Operating systems that are expected to fail the tests. See issue 13841.
var badOS = map[string]bool{ var badOS = map[string]bool{
"darwin": true, "darwin": true,
"netbsd": true, "netbsd": true,
"plan9": true, "plan9": true,
"dragonfly": true,
"solaris": true,
} }
func TestBlockProfile(t *testing.T) { func TestBlockProfile(t *testing.T) {
......
// 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")
}
}
}
}
// 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 ignore
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)
}
}
...@@ -312,13 +312,22 @@ func TestAppendSliceGrowth(t *testing.T) { ...@@ -312,13 +312,22 @@ func TestAppendSliceGrowth(t *testing.T) {
} }
func TestGoroutineProfileTrivial(t *testing.T) { func TestGoroutineProfileTrivial(t *testing.T) {
n1, ok := GoroutineProfile(nil) // should fail, there's at least 1 goroutine // Calling GoroutineProfile twice in a row should find the same number of goroutines,
if n1 < 1 || ok { // but it's possible there are goroutines just about to exit, so we might end up
t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok) // with fewer in the second call. Try a few times; it should converge once those
} // zombies are gone.
for i := 0; ; i++ {
n2, ok := GoroutineProfile(make([]StackRecord, n1)) n1, ok := GoroutineProfile(nil) // should fail, there's at least 1 goroutine
if n2 != n1 || !ok { if n1 < 1 || ok {
t.Fatalf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1) t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok)
}
n2, ok := GoroutineProfile(make([]StackRecord, n1))
if n2 == n1 && ok {
break
}
t.Logf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1)
if i >= 10 {
t.Fatalf("GoroutineProfile not converging")
}
} }
} }
...@@ -225,3 +225,18 @@ func TestRangeStringCast(t *testing.T) { ...@@ -225,3 +225,18 @@ func TestRangeStringCast(t *testing.T) {
t.Fatalf("want 0 allocs, got %v", n) 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))
}
}
...@@ -29,7 +29,7 @@ func init() { ...@@ -29,7 +29,7 @@ func init() {
register("GoexitInPanic", GoexitInPanic) register("GoexitInPanic", GoexitInPanic)
register("PanicAfterGoexit", PanicAfterGoexit) register("PanicAfterGoexit", PanicAfterGoexit)
register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit) register("RecoveredPanicAfterGoexit", RecoveredPanicAfterGoexit)
register("PanicTraceback", PanicTraceback)
} }
func SimpleDeadlock() { func SimpleDeadlock() {
...@@ -171,3 +171,21 @@ func RecoveredPanicAfterGoexit() { ...@@ -171,3 +171,21 @@ func RecoveredPanicAfterGoexit() {
}() }()
runtime.Goexit() runtime.Goexit()
} }
func PanicTraceback() {
pt1()
}
func pt1() {
defer func() {
panic("panic pt1")
}()
pt2()
}
func pt2() {
defer func() {
panic("panic pt2")
}()
panic("hello")
}
...@@ -128,13 +128,16 @@ func TestWaitGroupMisuse3(t *testing.T) { ...@@ -128,13 +128,16 @@ func TestWaitGroupMisuse3(t *testing.T) {
} }
}() }()
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4)) defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(4))
done := make(chan interface{}, 1) done := make(chan interface{}, 2)
// The detection is opportunistically, so we want it to panic // The detection is opportunistically, so we want it to panic
// at least in one run out of a million. // at least in one run out of a million.
for i := 0; i < 1e6; i++ { for i := 0; i < 1e6; i++ {
var wg WaitGroup var wg WaitGroup
wg.Add(1) wg.Add(1)
go func() { go func() {
defer func() {
done <- recover()
}()
wg.Done() wg.Done()
}() }()
go func() { go func() {
...@@ -150,8 +153,10 @@ func TestWaitGroupMisuse3(t *testing.T) { ...@@ -150,8 +153,10 @@ func TestWaitGroupMisuse3(t *testing.T) {
wg.Wait() wg.Wait()
}() }()
wg.Wait() wg.Wait()
if err := <-done; err != nil { for j := 0; j < 2; j++ {
panic(err) if err := <-done; err != nil {
panic(err)
}
} }
} }
t.Fatal("Should panic") t.Fatal("Should panic")
......
...@@ -23,6 +23,6 @@ __go_string_to_byte_array (String str) ...@@ -23,6 +23,6 @@ __go_string_to_byte_array (String str)
__builtin_memset (data + str.len, 0, cap - (uintptr) str.len); __builtin_memset (data + str.len, 0, cap - (uintptr) str.len);
ret.__values = (void *) data; ret.__values = (void *) data;
ret.__count = str.len; ret.__count = str.len;
ret.__capacity = (intgo) cap; ret.__capacity = str.len;
return ret; return ret;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment