[Pkg-golang-commits] [golang] 01/03: Imported Upstream version 1.6.2
Michael Hudson-Doyle
mwhudson-guest at moszumanska.debian.org
Fri Jun 3 02:36:14 UTC 2016
This is an automated email from the git hooks/post-receive script.
mwhudson-guest pushed a commit to branch debian-sid
in repository golang.
commit 15be393e05ed7e06c2e62cde6401d54a0584658a
Author: Michael Hudson-Doyle <michael.hudson at canonical.com>
Date: Fri Jun 3 14:06:42 2016 +1200
Imported Upstream version 1.6.2
---
CONTRIBUTING.md | 3 +-
VERSION | 2 +-
doc/contribute.html | 2 +-
doc/devel/release.html | 8 +++++
doc/go1.6.html | 4 +--
doc/go_faq.html | 3 +-
doc/install-source.html | 15 ++++++---
misc/cgo/errors/ptr.go | 10 ++++++
src/cmd/cgo/gcc.go | 11 ++++---
src/cmd/compile/internal/gc/esc.go | 5 +++
src/cmd/go/get.go | 8 +++++
src/cmd/go/go_test.go | 12 +++++++
src/cmd/go/pkg.go | 10 ++++--
src/cmd/go/vendor_test.go | 26 +++++++++++++++
src/cmd/link/internal/ld/macho.go | 5 +--
src/mime/multipart/formdata_test.go | 36 +++++++++++++++++++++
src/mime/multipart/multipart.go | 20 +++++++++++-
src/net/http/export_test.go | 6 ++--
src/net/http/serve_test.go | 26 +++++++++++++++
src/net/http/server.go | 28 ++++++++--------
src/net/http/transport.go | 10 ++++--
src/net/http/transport_test.go | 5 +++
src/runtime/cgocall.go | 3 ++
src/runtime/crash_cgo_test.go | 53 +++++++++++++++++++++++++++++++
src/runtime/export_test.go | 16 ++++++++++
src/runtime/gc_test.go | 17 ++++++++++
src/runtime/mgc.go | 14 +++++---
src/runtime/mheap.go | 2 +-
src/runtime/os1_windows.go | 35 +++++++++++---------
src/runtime/os_linux_386.go | 5 ---
src/runtime/panic.go | 17 ++++++++++
src/runtime/proc.go | 3 ++
src/runtime/rt0_darwin_arm.s | 28 ++++++++++------
src/runtime/rt0_darwin_arm64.s | 28 ++++++++++++----
src/runtime/rt0_linux_386.s | 8 -----
src/runtime/rt0_linux_arm64.s | 27 ++++++++++++----
src/runtime/runtime1.go | 2 +-
src/runtime/signal_386.go | 25 +--------------
src/runtime/symtab.go | 2 +-
src/runtime/sys_linux_386.s | 25 ++++++---------
src/runtime/sys_linux_amd64.s | 6 +++-
src/runtime/testdata/testprogcgo/aprof.go | 48 ++++++++++++++++++++++++++++
src/runtime/testdata/testprogcgo/cgo.go | 20 ++++++++++++
src/sort/sort.go | 14 ++++----
src/sort/sort_test.go | 37 +++++++++++++++++++++
src/syscall/asm_linux_386.s | 13 ++------
src/syscall/types_linux.go | 3 ++
src/syscall/ztypes_linux_ppc64.go | 7 ++--
src/syscall/ztypes_linux_ppc64le.go | 7 ++--
test/escape_closure.go | 26 +++++++++++++++
50 files changed, 584 insertions(+), 162 deletions(-)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 712431c..4120daf 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,7 +26,8 @@ Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html
before sending patches.
**We do not accept GitHub pull requests**
-(we use [Gerrit](https://code.google.com/p/gerrit/) instead for code review).
+(we use [an instance](https://go-review.googlesource.com/) of the
+[Gerrit](https://www.gerritcodereview.com/) code review system instead).
Unless otherwise noted, the Go source files are distributed under
the BSD-style license found in the LICENSE file.
diff --git a/VERSION b/VERSION
index e1bf218..17df20d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.6.1
\ No newline at end of file
+go1.6.2
\ No newline at end of file
diff --git a/doc/contribute.html b/doc/contribute.html
index 4619c81..59b3d20 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -78,7 +78,7 @@ no matter who makes the change.
A custom git command called <code>git-codereview</code>,
discussed below, helps manage the code review process through a Google-hosted
<a href="https://go-review.googlesource.com/">instance</a> of the code review
-system called <a href="https://code.google.com/p/gerrit/">Gerrit</a>.
+system called <a href="https://www.gerritcodereview.com/">Gerrit</a>.
</p>
<h3 id="auth">Set up authentication for code review</h3>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index e72f86d..a1a615f 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -45,6 +45,14 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.1">Go
1.6.1 milestone</a> on our issue tracker for details.
</p>
+<p>
+go1.6.2 (released 2016/04/20) includes fixes to the compiler, runtime, tools,
+documentation, and the <code>mime/multipart</code>, <code>net/http</code>, and
+<code>sort</code> packages.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.6.2">Go
+1.6.2 milestone</a> on our issue tracker for details.
+</p>
+
<h2 id="go1.5">go1.5 (released 2015/08/19)</h2>
<p>
diff --git a/doc/go1.6.html b/doc/go1.6.html
index 17c3536..8dea862 100644
--- a/doc/go1.6.html
+++ b/doc/go1.6.html
@@ -168,9 +168,7 @@ Go 1.7 will remove support for the old syntax.
<p>
The release schedules for the GCC and Go projects do not coincide.
GCC release 5 contains the Go 1.4 version of gccgo.
-The next release, GCC 6, will have the Go 1.5 version of gccgo.
-Due to release scheduling, it is likely that
-Go 1.6 will not be in a GCC release until GCC 7.
+The next release, GCC 6, will have the Go 1.6 version of gccgo.
</p>
<h3 id="go_command">Go command</h3>
diff --git a/doc/go_faq.html b/doc/go_faq.html
index b5f9772..c4c506b 100644
--- a/doc/go_faq.html
+++ b/doc/go_faq.html
@@ -335,7 +335,8 @@ code that does what generics would enable, if less smoothly.
</p>
<p>
-This remains an open issue.
+This remains an open issue. See <a href="https://golang.org/issue/15292">the generics proposal issue</a>
+for more information.
</p>
<h3 id="exceptions">
diff --git a/doc/install-source.html b/doc/install-source.html
index 7da5675..da71f47 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -194,14 +194,19 @@ To build without <code>cgo</code>, set the environment variable
<p>Go will install to a directory named <code>go</code>.
Change to the directory that will be its parent
and make sure the <code>go</code> directory does not exist.
-Then clone the repository and check out the latest release tag:</p>
+Then clone the repository and check out the latest release tag
+(<code class="versionTag">go1.6</code>, for example):</p>
<pre>
$ git clone https://go.googlesource.com/go
$ cd go
-$ git checkout go1.6
+$ git checkout <span class="versionTag"><i><tag></i></span>
</pre>
+<p class="whereTag">
+Where <code><tag></code> is the version string of the release.
+</p>
+
<h2 id="head">(Optional) Switch to the master branch</h2>
<p>If you intend to modify the go source code, and
@@ -378,7 +383,7 @@ New releases are announced on the
<a href="//groups.google.com/group/golang-announce">golang-announce</a>
mailing list.
Each announcement mentions the latest release tag, for instance,
-<code>go1.6</code>.
+<code class="versionTag">go1.6</code>.
</p>
<p>
@@ -388,11 +393,13 @@ To update an existing tree to the latest release, you can run:
<pre>
$ cd go/src
$ git fetch
-$ git checkout <i><tag></i>
+$ git checkout <span class="versionTag"><i><tag></i></psan>
$ ./all.bash
</pre>
+<p class="whereTag">
Where <code><tag></code> is the version string of the release.
+</p>
<h2 id="environment">Optional environment variables</h2>
diff --git a/misc/cgo/errors/ptr.go b/misc/cgo/errors/ptr.go
index 834cde9..bbcaaab 100644
--- a/misc/cgo/errors/ptr.go
+++ b/misc/cgo/errors/ptr.go
@@ -123,6 +123,16 @@ var ptrTests = []ptrTest{
fail: false,
},
{
+ // Passing the address of a slice of an array that is
+ // an element in a struct, with a type conversion.
+ name: "slice-ok-4",
+ c: `typedef void* PV; void f(PV p) {}`,
+ imports: []string{"unsafe"},
+ support: `type S struct { p *int; a [4]byte }`,
+ body: `i := 0; p := &S{p:&i}; C.f(C.PV(unsafe.Pointer(&p.a[0])))`,
+ fail: false,
+ },
+ {
// Passing the address of a static variable with no
// pointers doesn't matter.
name: "varok",
diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go
index fb5049c..e1456cb 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -819,14 +819,17 @@ func (p *Package) hasSideEffects(f *File, x ast.Expr) bool {
func (p *Package) isType(t ast.Expr) bool {
switch t := t.(type) {
case *ast.SelectorExpr:
- if t.Sel.Name != "Pointer" {
- return false
- }
id, ok := t.X.(*ast.Ident)
if !ok {
return false
}
- return id.Name == "unsafe"
+ if id.Name == "unsafe" && t.Sel.Name == "Pointer" {
+ return true
+ }
+ if id.Name == "C" && typedef["_Ctype_"+t.Sel.Name] != nil {
+ return true
+ }
+ return false
case *ast.Ident:
// TODO: This ignores shadowing.
switch t.Name {
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index ff983e7..06b6082 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -1376,6 +1376,11 @@ func esccall(e *EscState, n *Node, up *Node) {
if haspointers(t.Type) {
escassign(e, &e.theSink, src)
}
+ } else { // indirect and OCALLFUNC = could be captured variables, too. (#14409)
+ ll = e.nodeEscState(n).Escretval
+ for ; ll != nil; ll = ll.Next {
+ escassignDereference(e, ll.N, fn)
+ }
}
return
}
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
index a298049..9d4b94a 100644
--- a/src/cmd/go/get.go
+++ b/src/cmd/go/get.go
@@ -119,6 +119,14 @@ func runGet(cmd *Command, args []string) {
delete(packageCache, name)
}
+ // In order to rebuild packages information completely,
+ // we need to clear commands cache. Command packages are
+ // referring to evicted packages from the package cache.
+ // This leads to duplicated loads of the standard packages.
+ for name := range cmdCache {
+ delete(cmdCache, name)
+ }
+
args = importPaths(args)
packagesForBuild(args)
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index 39e0f3e..acf4a39 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -2759,3 +2759,15 @@ func TestParallelTest(t *testing.T) {
tg.setenv("GOPATH", tg.path("."))
tg.run("test", "-p=4", "p1", "p2", "p3", "p4")
}
+
+// Issue 14444: go get -u .../ duplicate loads errors
+func TestGoGetUpdateAllDoesNotTryToLoadDuplicates(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("get", "-u", ".../")
+ tg.grepStderrNot("duplicate loads of", "did not remove old packages from cache")
+}
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 0c0cf07..599c2b4 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -441,6 +441,12 @@ func vendoredImportPath(parent *Package, path string) (found string) {
}
targ := filepath.Join(dir[:i], vpath)
if isDir(targ) && hasGoFiles(targ) {
+ importPath := parent.ImportPath
+ if importPath == "command-line-arguments" {
+ // If parent.ImportPath is 'command-line-arguments'.
+ // set to relative directory to root (also chopped root directory)
+ importPath = dir[len(root)+1:]
+ }
// We started with parent's dir c:\gopath\src\foo\bar\baz\quux\xyzzy.
// We know the import path for parent's dir.
// We chopped off some number of path elements and
@@ -450,14 +456,14 @@ func vendoredImportPath(parent *Package, path string) (found string) {
// (actually the same number of bytes) from parent's import path
// and then append /vendor/path.
chopped := len(dir) - i
- if chopped == len(parent.ImportPath)+1 {
+ if chopped == len(importPath)+1 {
// We walked up from c:\gopath\src\foo\bar
// and found c:\gopath\src\vendor\path.
// We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).
// Use "vendor/path" without any prefix.
return vpath
}
- return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath
+ return importPath[:len(importPath)-chopped] + "/" + vpath
}
}
return path
diff --git a/src/cmd/go/vendor_test.go b/src/cmd/go/vendor_test.go
index 006a8c9..4cf2b0c 100644
--- a/src/cmd/go/vendor_test.go
+++ b/src/cmd/go/vendor_test.go
@@ -244,6 +244,32 @@ func TestVendorTest2(t *testing.T) {
tg.run("test", "github.com/rsc/go-get-issue-11864/vendor/vendor.org/tx2")
}
+func TestVendorTest3(t *testing.T) {
+ testenv.MustHaveExternalNetwork(t)
+
+ tg := testgo(t)
+ defer tg.cleanup()
+ tg.makeTempdir()
+ tg.setenv("GOPATH", tg.path("."))
+ tg.run("get", "github.com/clsung/go-vendor-issue-14613")
+
+ tg.run("build", "-i", "github.com/clsung/go-vendor-issue-14613")
+
+ // test folder should work
+ tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613")
+ tg.run("test", "github.com/clsung/go-vendor-issue-14613")
+
+ // test with specified _test.go should work too
+ tg.cd(filepath.Join(tg.path("."), "src"))
+ tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
+ tg.run("test", "github.com/clsung/go-vendor-issue-14613/vendor_test.go")
+
+ // test with imported and not used
+ tg.run("test", "-i", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
+ tg.runFail("test", "github.com/clsung/go-vendor-issue-14613/vendor/mylibtesttest/myapp/myapp_test.go")
+ tg.grepStderr("imported and not used:", `should say "imported and not used"`)
+}
+
func TestVendorList(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 1c7f3a0..cf3fba1 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -356,8 +356,9 @@ func machoshbits(mseg *MachoSeg, sect *Section, segname string) {
buf := "__" + strings.Replace(sect.Name[1:], ".", "_", -1)
var msect *MachoSect
- if sect.Rwx&1 == 0 && (Thearch.Thechar == '7' || (Thearch.Thechar == '6' && Buildmode == BuildmodeCShared)) {
- // Darwin external linker on arm64 and on amd64 in c-shared buildmode
+ if sect.Rwx&1 == 0 && (Thearch.Thechar == '7' || // arm64
+ (Thearch.Thechar == '6' && (Buildmode == BuildmodeCShared || Buildmode == BuildmodeCArchive))) { // amd64
+ // Darwin external linker on arm64 and on amd64 in c-shared/c-archive buildmode
// complains about absolute relocs in __TEXT, so if the section is not
// executable, put it in __DATA segment.
msect = newMachoSect(mseg, buf, "__DATA")
diff --git a/src/mime/multipart/formdata_test.go b/src/mime/multipart/formdata_test.go
index 6e2388b..1deca0b 100644
--- a/src/mime/multipart/formdata_test.go
+++ b/src/mime/multipart/formdata_test.go
@@ -88,3 +88,39 @@ Content-Disposition: form-data; name="textb"
` + textbValue + `
--MyBoundary--
`
+
+func TestReadForm_NoReadAfterEOF(t *testing.T) {
+ maxMemory := int64(32) << 20
+ boundary := `---------------------------8d345eef0d38dc9`
+ body := `
+-----------------------------8d345eef0d38dc9
+Content-Disposition: form-data; name="version"
+
+171
+-----------------------------8d345eef0d38dc9--`
+
+ mr := NewReader(&failOnReadAfterErrorReader{t: t, r: strings.NewReader(body)}, boundary)
+
+ f, err := mr.ReadForm(maxMemory)
+ if err != nil {
+ t.Fatal(err)
+ }
+ t.Logf("Got: %#v", f)
+}
+
+// failOnReadAfterErrorReader is an io.Reader wrapping r.
+// It fails t if any Read is called after a failing Read.
+type failOnReadAfterErrorReader struct {
+ t *testing.T
+ r io.Reader
+ sawErr error
+}
+
+func (r *failOnReadAfterErrorReader) Read(p []byte) (n int, err error) {
+ if r.sawErr != nil {
+ r.t.Fatalf("unexpected Read on Reader after previous read saw error %v", r.sawErr)
+ }
+ n, err = r.r.Read(p)
+ r.sawErr = err
+ return
+}
diff --git a/src/mime/multipart/multipart.go b/src/mime/multipart/multipart.go
index 3b746a5..c21c3fc 100644
--- a/src/mime/multipart/multipart.go
+++ b/src/mime/multipart/multipart.go
@@ -96,7 +96,7 @@ func (p *Part) parseContentDisposition() {
func NewReader(r io.Reader, boundary string) *Reader {
b := []byte("\r\n--" + boundary + "--")
return &Reader{
- bufReader: bufio.NewReaderSize(r, peekBufferSize),
+ bufReader: bufio.NewReaderSize(&stickyErrorReader{r: r}, peekBufferSize),
nl: b[:2],
nlDashBoundary: b[:len(b)-2],
dashBoundaryDash: b[2:],
@@ -104,6 +104,24 @@ func NewReader(r io.Reader, boundary string) *Reader {
}
}
+// stickyErrorReader is an io.Reader which never calls Read on its
+// underlying Reader once an error has been seen. (the io.Reader
+// interface's contract promises nothing about the return values of
+// Read calls after an error, yet this package does do multiple Reads
+// after error)
+type stickyErrorReader struct {
+ r io.Reader
+ err error
+}
+
+func (r *stickyErrorReader) Read(p []byte) (n int, _ error) {
+ if r.err != nil {
+ return 0, r.err
+ }
+ n, r.err = r.r.Read(p)
+ return n, r.err
+}
+
func newPart(mr *Reader) (*Part, error) {
bp := &Part{
Header: make(map[string][]string),
diff --git a/src/net/http/export_test.go b/src/net/http/export_test.go
index 52bccbd..7952e00 100644
--- a/src/net/http/export_test.go
+++ b/src/net/http/export_test.go
@@ -59,9 +59,9 @@ func SetTestHookServerServe(fn func(*Server, net.Listener)) { testHookServerServ
func NewTestTimeoutHandler(handler Handler, ch <-chan time.Time) Handler {
return &timeoutHandler{
- handler: handler,
- timeout: func() <-chan time.Time { return ch },
- // (no body and nil cancelTimer)
+ handler: handler,
+ testTimeout: ch,
+ // (no body)
}
}
diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go
index 384b453..f79c045 100644
--- a/src/net/http/serve_test.go
+++ b/src/net/http/serve_test.go
@@ -1888,6 +1888,32 @@ func TestTimeoutHandlerRaceHeaderTimeout(t *testing.T) {
}
}
+// Issue 14568.
+func TestTimeoutHandlerStartTimerWhenServing(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping sleeping test in -short mode")
+ }
+ defer afterTest(t)
+ var handler HandlerFunc = func(w ResponseWriter, _ *Request) {
+ w.WriteHeader(StatusNoContent)
+ }
+ timeout := 300 * time.Millisecond
+ ts := httptest.NewServer(TimeoutHandler(handler, timeout, ""))
+ defer ts.Close()
+ // Issue was caused by the timeout handler starting the timer when
+ // was created, not when the request. So wait for more than the timeout
+ // to ensure that's not the case.
+ time.Sleep(2 * timeout)
+ res, err := Get(ts.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer res.Body.Close()
+ if res.StatusCode != StatusNoContent {
+ t.Errorf("got res.StatusCode %d, want %v", res.StatusCode, StatusNoContent)
+ }
+}
+
// Verifies we don't path.Clean() on the wrong parts in redirects.
func TestRedirectMunging(t *testing.T) {
req, _ := NewRequest("GET", "http://example.com/", nil)
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 5e3b608..f23ef73 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -2309,15 +2309,10 @@ func (srv *Server) onceSetNextProtoDefaults() {
// TimeoutHandler buffers all Handler writes to memory and does not
// support the Hijacker or Flusher interfaces.
func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
- t := time.NewTimer(dt)
return &timeoutHandler{
handler: h,
body: msg,
-
- // Effectively storing a *time.Timer, but decomposed
- // for testing:
- timeout: func() <-chan time.Time { return t.C },
- cancelTimer: t.Stop,
+ dt: dt,
}
}
@@ -2328,12 +2323,11 @@ var ErrHandlerTimeout = errors.New("http: Handler timeout")
type timeoutHandler struct {
handler Handler
body string
+ dt time.Duration
- // timeout returns the channel of a *time.Timer and
- // cancelTimer cancels it. They're stored separately for
- // testing purposes.
- timeout func() <-chan time.Time // returns channel producing a timeout
- cancelTimer func() bool // optional
+ // When set, no timer will be created and this channel will
+ // be used instead.
+ testTimeout <-chan time.Time
}
func (h *timeoutHandler) errorBody() string {
@@ -2344,6 +2338,12 @@ func (h *timeoutHandler) errorBody() string {
}
func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
+ var t *time.Timer
+ timeout := h.testTimeout
+ if timeout == nil {
+ t = time.NewTimer(h.dt)
+ timeout = t.C
+ }
done := make(chan struct{})
tw := &timeoutWriter{
w: w,
@@ -2363,10 +2363,10 @@ func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
}
w.WriteHeader(tw.code)
w.Write(tw.wbuf.Bytes())
- if h.cancelTimer != nil {
- h.cancelTimer()
+ if t != nil {
+ t.Stop()
}
- case <-h.timeout():
+ case <-timeout:
tw.mu.Lock()
defer tw.mu.Unlock()
w.WriteHeader(StatusServiceUnavailable)
diff --git a/src/net/http/transport.go b/src/net/http/transport.go
index baf71d5..1e3ea11 100644
--- a/src/net/http/transport.go
+++ b/src/net/http/transport.go
@@ -176,9 +176,13 @@ func (t *Transport) onceSetNextProtoDefaults() {
// Issue 14275.
return
}
- if t.ExpectContinueTimeout != 0 {
- // Unsupported in http2, so disable http2 for now.
- // Issue 13851.
+ if t.ExpectContinueTimeout != 0 && t != DefaultTransport {
+ // ExpectContinueTimeout is unsupported in http2, so
+ // if they explicitly asked for it (as opposed to just
+ // using the DefaultTransport, which sets it), then
+ // disable http2 for now.
+ //
+ // Issue 13851. (and changed in Issue 14391)
return
}
t2, err := http2configureTransport(t)
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 0c901b3..d9da078 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -2888,6 +2888,11 @@ func TestTransportAutomaticHTTP2(t *testing.T) {
testTransportAutoHTTP(t, &Transport{}, true)
}
+// golang.org/issue/14391: also check DefaultTransport
+func TestTransportAutomaticHTTP2_DefaultTransport(t *testing.T) {
+ testTransportAutoHTTP(t, DefaultTransport.(*Transport), true)
+}
+
func TestTransportAutomaticHTTP2_TLSNextProto(t *testing.T) {
testTransportAutoHTTP(t, &Transport{
TLSNextProto: make(map[string]func(string, *tls.Conn) RoundTripper),
diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go
index 66115fd..fef8add 100644
--- a/src/runtime/cgocall.go
+++ b/src/runtime/cgocall.go
@@ -463,6 +463,9 @@ func cgoCheckArg(t *_type, p unsafe.Pointer, indir, top bool, msg string) {
if !top {
panic(errorString(msg))
}
+ if st.elem.kind&kindNoPointers != 0 {
+ return
+ }
for i := 0; i < s.cap; i++ {
cgoCheckArg(st.elem, p, true, false, msg)
p = add(p, st.elem.size)
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index d7b367f..1802e49 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -7,10 +7,13 @@
package runtime_test
import (
+ "fmt"
+ "internal/testenv"
"os/exec"
"runtime"
"strings"
"testing"
+ "time"
)
func TestCgoCrashHandler(t *testing.T) {
@@ -147,3 +150,53 @@ func TestEnsureDropM(t *testing.T) {
t.Errorf("expected %q, got %v", want, got)
}
}
+
+// Test for issue 14387.
+// Test that the program that doesn't need any cgo pointer checking
+// takes about the same amount of time with it as without it.
+func TestCgoCheckBytes(t *testing.T) {
+ // Make sure we don't count the build time as part of the run time.
+ testenv.MustHaveGoBuild(t)
+ exe, err := buildTestProg(t, "testprogcgo")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Try it 10 times to avoid flakiness.
+ const tries = 10
+ var tot1, tot2 time.Duration
+ for i := 0; i < tries; i++ {
+ cmd := testEnv(exec.Command(exe, "CgoCheckBytes"))
+ cmd.Env = append(cmd.Env, "GODEBUG=cgocheck=0", fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
+
+ start := time.Now()
+ cmd.Run()
+ d1 := time.Since(start)
+
+ cmd = testEnv(exec.Command(exe, "CgoCheckBytes"))
+ cmd.Env = append(cmd.Env, fmt.Sprintf("GO_CGOCHECKBYTES_TRY=%d", i))
+
+ start = time.Now()
+ cmd.Run()
+ d2 := time.Since(start)
+
+ if d1*20 > d2 {
+ // The slow version (d2) was less than 20 times
+ // slower than the fast version (d1), so OK.
+ return
+ }
+
+ tot1 += d1
+ tot2 += d2
+ }
+
+ t.Errorf("cgo check too slow: got %v, expected at most %v", tot2/tries, (tot1/tries)*20)
+}
+
+func TestCgoCCodeSIGPROF(t *testing.T) {
+ got := runTestProg(t, "testprogcgo", "CgoCCodeSIGPROF")
+ want := "OK\n"
+ if got != want {
+ t.Errorf("expected %q got %v", want, got)
+ }
+}
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 5400c1d..4380908 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -171,3 +171,19 @@ func SetTracebackEnv(level string) {
setTraceback(level)
traceback_env = traceback_cache
}
+
+func CountPagesInUse() (pagesInUse, counted uintptr) {
+ stopTheWorld("CountPagesInUse")
+
+ pagesInUse = uintptr(mheap_.pagesInUse)
+
+ for _, s := range h_allspans {
+ if s.state == mSpanInUse {
+ counted += s.npages
+ }
+ }
+
+ startTheWorld()
+
+ return
+}
diff --git a/src/runtime/gc_test.go b/src/runtime/gc_test.go
index c8c96bb..d53d3ee 100644
--- a/src/runtime/gc_test.go
+++ b/src/runtime/gc_test.go
@@ -473,3 +473,20 @@ func testIfaceEqual(x interface{}) {
a = true
}
}
+
+func TestPageAccounting(t *testing.T) {
+ // Grow the heap in small increments. This used to drop the
+ // pages-in-use count below zero because of a rounding
+ // mismatch (golang.org/issue/15022).
+ const blockSize = 64 << 10
+ blocks := make([]*[blockSize]byte, (64<<20)/blockSize)
+ for i := range blocks {
+ blocks[i] = new([blockSize]byte)
+ }
+
+ // Check that the running page count matches reality.
+ pagesInUse, counted := runtime.CountPagesInUse()
+ if pagesInUse != counted {
+ t.Fatalf("mheap_.pagesInUse is %d, but direct count is %d", pagesInUse, counted)
+ }
+}
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 94301c6..ab099d8 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -932,6 +932,9 @@ func gcStart(mode gcMode, forceTrigger bool) {
if mode == gcBackgroundMode {
gcBgMarkStartWorkers()
}
+
+ gcResetMarkState()
+
now := nanotime()
work.stwprocs, work.maxprocs = gcprocs(), gomaxprocs
work.tSweepTerm = now
@@ -949,8 +952,6 @@ func gcStart(mode gcMode, forceTrigger bool) {
// reclaimed until the next GC cycle.
clearpools()
- gcResetMarkState()
-
work.finalizersDone = false
if mode == gcBackgroundMode { // Do as much work concurrently as possible
@@ -1559,7 +1560,8 @@ func gcMark(start_time int64) {
gcDrain(&gcw, gcDrainBlock)
gcw.dispose()
- gcMarkRootCheck()
+ // TODO: Re-enable once this is cheap.
+ //gcMarkRootCheck()
if work.full != 0 {
throw("work.full != 0")
}
@@ -1723,8 +1725,10 @@ func gcCopySpans() {
}
// gcResetMarkState resets global state prior to marking (concurrent
-// or STW) and resets the stack scan state of all Gs. Any Gs created
-// after this will also be in the reset state.
+// or STW) and resets the stack scan state of all Gs.
+//
+// This is safe to do without the world stopped because any Gs created
+// during or after this will start out in the reset state.
func gcResetMarkState() {
// This may be called during a concurrent phase, so make sure
// allgs doesn't change.
diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go
index e818954..a153df0 100644
--- a/src/runtime/mheap.go
+++ b/src/runtime/mheap.go
@@ -671,7 +671,7 @@ func (h *mheap) grow(npage uintptr) bool {
}
atomic.Store(&s.sweepgen, h.sweepgen)
s.state = _MSpanInUse
- h.pagesInUse += uint64(npage)
+ h.pagesInUse += uint64(s.npages)
h.freeSpanLocked(s, false, true, 0)
return true
}
diff --git a/src/runtime/os1_windows.go b/src/runtime/os1_windows.go
index b4411da..8e41ac3 100644
--- a/src/runtime/os1_windows.go
+++ b/src/runtime/os1_windows.go
@@ -108,23 +108,28 @@ func asmstdcall(fn unsafe.Pointer)
var asmstdcallAddr unsafe.Pointer
+func windowsFindfunc(name []byte, lib uintptr) stdFunction {
+ f := stdcall2(_GetProcAddress, lib, uintptr(unsafe.Pointer(&name[0])))
+ return stdFunction(unsafe.Pointer(f))
+}
+
func loadOptionalSyscalls() {
- var buf [50]byte // large enough for longest string
- strtoptr := func(s string) uintptr {
- buf[copy(buf[:], s)] = 0 // nil-terminated for OS
- return uintptr(noescape(unsafe.Pointer(&buf[0])))
- }
- l := stdcall1(_LoadLibraryA, strtoptr("kernel32.dll"))
- findfunc := func(name string) stdFunction {
- f := stdcall2(_GetProcAddress, l, strtoptr(name))
- return stdFunction(unsafe.Pointer(f))
- }
- if l != 0 {
- _AddDllDirectory = findfunc("AddDllDirectory")
- _AddVectoredContinueHandler = findfunc("AddVectoredContinueHandler")
- _GetQueuedCompletionStatusEx = findfunc("GetQueuedCompletionStatusEx")
- _LoadLibraryExW = findfunc("LoadLibraryExW")
+ var (
+ kernel32dll = []byte("kernel32.dll\000")
+ addVectoredContinueHandler = []byte("AddVectoredContinueHandler\000")
+ getQueuedCompletionStatusEx = []byte("GetQueuedCompletionStatusEx\000")
+ addDllDirectory = []byte("AddDllDirectory\000")
+ loadLibraryExW = []byte("LoadLibraryExW\000")
+ )
+
+ k32 := stdcall1(_LoadLibraryA, uintptr(unsafe.Pointer(&kernel32dll[0])))
+ if k32 == 0 {
+ throw("kernel32.dll not found")
}
+ _AddDllDirectory = windowsFindfunc(addDllDirectory, k32)
+ _AddVectoredContinueHandler = windowsFindfunc(addVectoredContinueHandler, k32)
+ _GetQueuedCompletionStatusEx = windowsFindfunc(getQueuedCompletionStatusEx, k32)
+ _LoadLibraryExW = windowsFindfunc(loadLibraryExW, k32)
}
//go:nosplit
diff --git a/src/runtime/os_linux_386.go b/src/runtime/os_linux_386.go
index 3577a24..0f39cad 100644
--- a/src/runtime/os_linux_386.go
+++ b/src/runtime/os_linux_386.go
@@ -15,8 +15,6 @@ const (
_AT_SYSINFO = 32
)
-var _vdso uint32
-
func sysargs(argc int32, argv **byte) {
// skip over argv, envv to get to auxv
n := argc + 1
@@ -28,9 +26,6 @@ func sysargs(argc int32, argv **byte) {
for i := 0; auxv[i] != _AT_NULL; i += 2 {
switch auxv[i] {
- case _AT_SYSINFO:
- _vdso = auxv[i+1]
-
case _AT_RANDOM:
startupRandomData = (*[16]byte)(unsafe.Pointer(uintptr(auxv[i+1])))[:]
}
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index ba07330..3d9d035 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -9,39 +9,56 @@ import (
"unsafe"
)
+// Calling panic with one of the errors below will call errorString.Error
+// which will call mallocgc to concatenate strings. That will fail if
+// malloc is locked, causing a confusing error message. Throw a better
+// error message instead.
+func panicCheckMalloc(err error) {
+ gp := getg()
+ if gp != nil && gp.m != nil && gp.m.mallocing != 0 {
+ throw(string(err.(errorString)))
+ }
+}
+
var indexError = error(errorString("index out of range"))
func panicindex() {
+ panicCheckMalloc(indexError)
panic(indexError)
}
var sliceError = error(errorString("slice bounds out of range"))
func panicslice() {
+ panicCheckMalloc(sliceError)
panic(sliceError)
}
var divideError = error(errorString("integer divide by zero"))
func panicdivide() {
+ panicCheckMalloc(divideError)
panic(divideError)
}
var overflowError = error(errorString("integer overflow"))
func panicoverflow() {
+ panicCheckMalloc(overflowError)
panic(overflowError)
}
var floatError = error(errorString("floating point error"))
func panicfloat() {
+ panicCheckMalloc(floatError)
panic(floatError)
}
var memoryError = error(errorString("invalid memory address or nil pointer dereference"))
func panicmem() {
+ panicCheckMalloc(memoryError)
panic(memoryError)
}
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index d1f5088..47ccb37 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -443,6 +443,9 @@ func schedinit() {
sched.lastpoll = uint64(nanotime())
procs := int(ncpu)
+ if procs > _MaxGomaxprocs {
+ procs = _MaxGomaxprocs
+ }
if n := atoi(gogetenv("GOMAXPROCS")); n > 0 {
if n > _MaxGomaxprocs {
n = _MaxGomaxprocs
diff --git a/src/runtime/rt0_darwin_arm.s b/src/runtime/rt0_darwin_arm.s
index cbbea80..59733d3 100644
--- a/src/runtime/rt0_darwin_arm.s
+++ b/src/runtime/rt0_darwin_arm.s
@@ -16,12 +16,15 @@ TEXT _rt0_arm_darwin(SB),7,$-4
//
// Note that all currently shipping darwin/arm platforms require
// cgo and do not support c-shared.
-TEXT _rt0_arm_darwin_lib(SB),NOSPLIT,$0
- // R11 is REGTMP, reserved for liblink. It is used below to
- // move R0/R1 into globals. However in the darwin ARMv7 calling
- // convention, it is a callee-saved register. So we save it to a
- // temporary register.
- MOVW R11, R2
+TEXT _rt0_arm_darwin_lib(SB),NOSPLIT,$32
+ // Preserve callee-save registers.
+ MOVW R4, 12(R13)
+ MOVW R5, 16(R13)
+ MOVW R6, 20(R13)
+ MOVW R7, 24(R13)
+ MOVW R8, 28(R13)
+ MOVW R11, 32(R13)
+
MOVW R0, _rt0_arm_darwin_lib_argc<>(SB)
MOVW R1, _rt0_arm_darwin_lib_argv<>(SB)
@@ -35,9 +38,8 @@ TEXT _rt0_arm_darwin_lib(SB),NOSPLIT,$0
B.EQ nocgo
MOVW $_rt0_arm_darwin_lib_go(SB), R0
MOVW $0, R1
- MOVW R2, R11
BL (R3)
- RET
+ B rr
nocgo:
MOVW $0x400000, R0
MOVW R0, (R13) // stacksize
@@ -46,10 +48,18 @@ nocgo:
MOVW $0, R0
MOVW R0, 8(R13) // fnarg
MOVW $runtime·newosproc0(SB), R3
- MOVW R2, R11
BL (R3)
+rr:
+ // Restore callee-save registers and return.
+ MOVW 12(R13), R4
+ MOVW 16(R13), R5
+ MOVW 20(R13), R6
+ MOVW 24(R13), R7
+ MOVW 28(R13), R8
+ MOVW 32(R13), R11
RET
+
TEXT _rt0_arm_darwin_lib_go(SB),NOSPLIT,$0
MOVW _rt0_arm_darwin_lib_argc<>(SB), R0
MOVW _rt0_arm_darwin_lib_argv<>(SB), R1
diff --git a/src/runtime/rt0_darwin_arm64.s b/src/runtime/rt0_darwin_arm64.s
index fa676c0..0a1feb1 100644
--- a/src/runtime/rt0_darwin_arm64.s
+++ b/src/runtime/rt0_darwin_arm64.s
@@ -16,12 +16,17 @@ TEXT _rt0_arm64_darwin(SB),NOSPLIT,$-8
//
// Note that all currently shipping darwin/arm64 platforms require
// cgo and do not support c-shared.
-TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$0
- // R27 is REGTMP, reserved for liblink. It is used below to
- // move R0/R1 into globals. However in the standard ARM64 calling
- // convention, it is a callee-saved register. So we save it to a
- // temporary register.
- MOVD R27, R7
+TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$88
+ // Preserve callee-save registers.
+ MOVD R19, 24(RSP)
+ MOVD R20, 32(RSP)
+ MOVD R21, 40(RSP)
+ MOVD R22, 48(RSP)
+ MOVD R23, 56(RSP)
+ MOVD R24, 64(RSP)
+ MOVD R25, 72(RSP)
+ MOVD R26, 80(RSP)
+ MOVD R27, 88(RSP)
MOVD R0, _rt0_arm64_darwin_lib_argc<>(SB)
MOVD R1, _rt0_arm64_darwin_lib_argv<>(SB)
@@ -36,7 +41,16 @@ TEXT _rt0_arm64_darwin_lib(SB),NOSPLIT,$0
MOVD $0, R1
BL (R4)
- MOVD R7, R27
+ // Restore callee-save registers.
+ MOVD 24(RSP), R19
+ MOVD 32(RSP), R20
+ MOVD 40(RSP), R21
+ MOVD 48(RSP), R22
+ MOVD 56(RSP), R23
+ MOVD 64(RSP), R24
+ MOVD 72(RSP), R25
+ MOVD 80(RSP), R26
+ MOVD 88(RSP), R27
RET
TEXT _rt0_arm64_darwin_lib_go(SB),NOSPLIT,$0
diff --git a/src/runtime/rt0_linux_386.s b/src/runtime/rt0_linux_386.s
index 59a30b4..23bfc98 100644
--- a/src/runtime/rt0_linux_386.s
+++ b/src/runtime/rt0_linux_386.s
@@ -73,11 +73,3 @@ GLOBL _rt0_386_linux_lib_argv<>(SB),NOPTR, $4
TEXT main(SB),NOSPLIT,$0
JMP runtime·rt0_go(SB)
-
-TEXT _fallback_vdso(SB),NOSPLIT,$0
- INT $0x80
- RET
-
-DATA runtime·_vdso(SB)/4, $_fallback_vdso(SB)
-GLOBL runtime·_vdso(SB), NOPTR, $4
-
diff --git a/src/runtime/rt0_linux_arm64.s b/src/runtime/rt0_linux_arm64.s
index 2b32e35..31c2367 100644
--- a/src/runtime/rt0_linux_arm64.s
+++ b/src/runtime/rt0_linux_arm64.s
@@ -11,11 +11,17 @@ TEXT _rt0_arm64_linux(SB),NOSPLIT,$-8
// When building with -buildmode=c-shared, this symbol is called when the shared
// library is loaded.
-TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$40
- // R27 is REGTMP, reserved for liblink. It is used below to
- // move R0/R1 into globals. However in the standard ARM64 calling
- // convention, it is a callee-saved register.
- MOVD R27, 24(RSP)
+TEXT _rt0_arm64_linux_lib(SB),NOSPLIT,$88
+ // Preserve callee-save registers.
+ MOVD R19, 24(RSP)
+ MOVD R20, 32(RSP)
+ MOVD R21, 40(RSP)
+ MOVD R22, 48(RSP)
+ MOVD R23, 56(RSP)
+ MOVD R24, 64(RSP)
+ MOVD R25, 72(RSP)
+ MOVD R26, 80(RSP)
+ MOVD R27, 88(RSP)
MOVD R0, _rt0_arm64_linux_lib_argc<>(SB)
MOVD R1, _rt0_arm64_linux_lib_argv<>(SB)
@@ -42,7 +48,16 @@ nocgo:
BL (R4)
restore:
- MOVD 24(RSP), R27
+ // Restore callee-save registers.
+ MOVD 24(RSP), R19
+ MOVD 32(RSP), R20
+ MOVD 40(RSP), R21
+ MOVD 48(RSP), R22
+ MOVD 56(RSP), R23
+ MOVD 64(RSP), R24
+ MOVD 72(RSP), R25
+ MOVD 80(RSP), R26
+ MOVD 88(RSP), R27
RET
TEXT _rt0_arm64_linux_lib_go(SB),NOSPLIT,$0
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index f63e09c..400ea29 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -52,7 +52,7 @@ var (
argv **byte
)
-// nosplit for use in linux/386 startup linux_setup_vdso
+// nosplit for use in linux startup sysargs
//go:nosplit
func argv_index(argv **byte, i int32) *byte {
return *(**byte)(add(unsafe.Pointer(argv), uintptr(i)*sys.PtrSize))
diff --git a/src/runtime/signal_386.go b/src/runtime/signal_386.go
index 0374f4a..25187da 100644
--- a/src/runtime/signal_386.go
+++ b/src/runtime/signal_386.go
@@ -142,30 +142,7 @@ func sighandler(sig uint32, info *siginfo, ctxt unsafe.Pointer, gp *g) {
level, _, docrash := gotraceback()
if level > 0 {
goroutineheader(gp)
-
- // On Linux/386, all system calls go through the vdso kernel_vsyscall routine.
- // Normally we don't see those PCs, but during signals we can.
- // If we see a PC in the vsyscall area (it moves around, but near the top of memory),
- // assume we're blocked in the vsyscall routine, which has saved
- // three words on the stack after the initial call saved the caller PC.
- // Pop all four words off SP and use the saved PC.
- // The check of the stack bounds here should suffice to avoid a fault
- // during the actual PC pop.
- // If we do load a bogus PC, not much harm done: we weren't going
- // to get a decent traceback anyway.
- // TODO(rsc): Make this more precise: we should do more checks on the PC,
- // and we should find out whether different versions of the vdso page
- // use different prologues that store different amounts on the stack.
- pc := uintptr(c.eip())
- sp := uintptr(c.esp())
- if GOOS == "linux" && pc >= 0xf4000000 && gp.stack.lo <= sp && sp+16 <= gp.stack.hi {
- // Assume in vsyscall page.
- sp += 16
- pc = *(*uintptr)(unsafe.Pointer(sp - 4))
- print("runtime: unwind vdso kernel_vsyscall: pc=", hex(pc), " sp=", hex(sp), "\n")
- }
-
- tracebacktrap(pc, sp, 0, gp)
+ tracebacktrap(uintptr(c.eip()), uintptr(c.esp()), 0, gp)
if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
// tracebackothers on original m skipped this one; trace it now.
goroutineheader(_g_.m.curg)
diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go
index 00b0a85..6e02f1e 100644
--- a/src/runtime/symtab.go
+++ b/src/runtime/symtab.go
@@ -199,7 +199,7 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
func findmoduledatap(pc uintptr) *moduledata {
for datap := &firstmoduledata; datap != nil; datap = datap.next {
- if datap.minpc <= pc && pc <= datap.maxpc {
+ if datap.minpc <= pc && pc < datap.maxpc {
return datap
}
}
diff --git a/src/runtime/sys_linux_386.s b/src/runtime/sys_linux_386.s
index 1a3aaf0..4a74196 100644
--- a/src/runtime/sys_linux_386.s
+++ b/src/runtime/sys_linux_386.s
@@ -12,16 +12,17 @@
// Most linux systems use glibc's dynamic linker, which puts the
// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position
-// independent code and setldt in this file does the same in the statically
-// linked case. Android, however, uses bionic's dynamic linker, which does not
-// save the helper anywhere, and so the only way to invoke a syscall from
-// position independent code is boring old int $0x80 (which is also what
-// bionic's syscall wrappers use).
-#ifdef GOOS_android
+// independent code and setldt in runtime does the same in the statically
+// linked case. However, systems that use alternative libc such as Android's
+// bionic and musl, do not save the helper anywhere, and so the only way to
+// invoke a syscall from position independent code is boring old int $0x80
+// (which is also what syscall wrappers in bionic/musl use).
+//
+// The benchmarks also showed that using int $0x80 is as fast as calling
+// *%gs:0x10 except on AMD Opteron. See https://golang.org/cl/19833
+// for the benchmark program and raw data.
+//#define INVOKE_SYSCALL CALL 0x10(GS) // non-portable
#define INVOKE_SYSCALL INT $0x80
-#else
-#define INVOKE_SYSCALL CALL 0x10(GS)
-#endif
TEXT runtime·exit(SB),NOSPLIT,$0
MOVL $252, AX // syscall number
@@ -434,12 +435,6 @@ TEXT runtime·setldt(SB),NOSPLIT,$32
*/
ADDL $0x4, DX // address
MOVL DX, 0(DX)
- // We copy the glibc dynamic linker behaviour of storing the
- // __kernel_vsyscall entry point at 0x10(GS) so that it can be invoked
- // by "CALL 0x10(GS)" in all situations, not only those where the
- // binary is actually dynamically linked.
- MOVL runtime·_vdso(SB), AX
- MOVL AX, 0x10(DX)
#endif
// set up user_desc
diff --git a/src/runtime/sys_linux_amd64.s b/src/runtime/sys_linux_amd64.s
index aed85cb..f407078 100644
--- a/src/runtime/sys_linux_amd64.s
+++ b/src/runtime/sys_linux_amd64.s
@@ -258,7 +258,7 @@ TEXT runtime·sysMmap(SB),NOSPLIT,$0
// Call the function stored in _cgo_mmap using the GCC calling convention.
// This must be called on the system stack.
-TEXT runtime·callCgoMmap(SB),NOSPLIT,$0
+TEXT runtime·callCgoMmap(SB),NOSPLIT,$16
MOVQ addr+0(FP), DI
MOVQ n+8(FP), SI
MOVL prot+16(FP), DX
@@ -266,7 +266,11 @@ TEXT runtime·callCgoMmap(SB),NOSPLIT,$0
MOVL fd+24(FP), R8
MOVL off+28(FP), R9
MOVQ _cgo_mmap(SB), AX
+ MOVQ SP, BX
+ ANDQ $~15, SP // alignment as per amd64 psABI
+ MOVQ BX, 0(SP)
CALL AX
+ MOVQ 0(SP), SP
MOVQ AX, ret+32(FP)
RET
diff --git a/src/runtime/testdata/testprogcgo/aprof.go b/src/runtime/testdata/testprogcgo/aprof.go
new file mode 100644
index 0000000..cf52107
--- /dev/null
+++ b/src/runtime/testdata/testprogcgo/aprof.go
@@ -0,0 +1,48 @@
+// 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 main
+
+// Test that SIGPROF received in C code does not crash the process
+// looking for the C code's func pointer.
+
+// The test fails when the function is the first C function.
+// The exported functions are the first C functions, so we use that.
+
+// extern void GoNop();
+import "C"
+
+import (
+ "bytes"
+ "fmt"
+ "runtime/pprof"
+)
+
+func init() {
+ register("CgoCCodeSIGPROF", CgoCCodeSIGPROF)
+}
+
+//export GoNop
+func GoNop() {}
+
+func CgoCCodeSIGPROF() {
+ c := make(chan bool)
+ go func() {
+ for {
+ <-c
+ for i := 0; i < 1e7; i++ {
+ C.GoNop()
+ }
+ c <- true
+ }
+ }()
+
+ var buf bytes.Buffer
+ pprof.StartCPUProfile(&buf)
+ c <- true
+ <-c
+ pprof.StopCPUProfile()
+
+ fmt.Println("OK")
+}
diff --git a/src/runtime/testdata/testprogcgo/cgo.go b/src/runtime/testdata/testprogcgo/cgo.go
index cf1af82..7a2e013 100644
--- a/src/runtime/testdata/testprogcgo/cgo.go
+++ b/src/runtime/testdata/testprogcgo/cgo.go
@@ -6,17 +6,22 @@ package main
/*
void foo1(void) {}
+void foo2(void* p) {}
*/
import "C"
import (
"fmt"
+ "os"
"runtime"
+ "strconv"
"time"
+ "unsafe"
)
func init() {
register("CgoSignalDeadlock", CgoSignalDeadlock)
register("CgoTraceback", CgoTraceback)
+ register("CgoCheckBytes", CgoCheckBytes)
}
func CgoSignalDeadlock() {
@@ -78,3 +83,18 @@ func CgoTraceback() {
runtime.Stack(buf, true)
fmt.Printf("OK\n")
}
+
+func CgoCheckBytes() {
+ try, _ := strconv.Atoi(os.Getenv("GO_CGOCHECKBYTES_TRY"))
+ if try <= 0 {
+ try = 1
+ }
+ b := make([]byte, 1e6*try)
+ start := time.Now()
+ for i := 0; i < 1e3*try; i++ {
+ C.foo2(unsafe.Pointer(&b[0]))
+ if time.Since(start) > time.Second {
+ break
+ }
+ }
+}
diff --git a/src/sort/sort.go b/src/sort/sort.go
index ac8f4a6..ee437d3 100644
--- a/src/sort/sort.go
+++ b/src/sort/sort.go
@@ -119,15 +119,15 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
pivot := lo
a, c := lo+1, hi-1
- for ; a != c && data.Less(a, pivot); a++ {
+ for ; a < c && data.Less(a, pivot); a++ {
}
b := a
for {
- for ; b != c && !data.Less(pivot, b); b++ { // data[b] <= pivot
+ for ; b < c && !data.Less(pivot, b); b++ { // data[b] <= pivot
}
- for ; b != c && data.Less(pivot, c-1); c-- { // data[c-1] > pivot
+ for ; b < c && data.Less(pivot, c-1); c-- { // data[c-1] > pivot
}
- if b == c {
+ if b >= c {
break
}
// data[b] > pivot; data[c-1] <= pivot
@@ -167,11 +167,11 @@ func doPivot(data Interface, lo, hi int) (midlo, midhi int) {
// data[a <= i < b] unexamined
// data[b <= i < c] = pivot
for {
- for ; a != b && !data.Less(b-1, pivot); b-- { // data[b] == pivot
+ for ; a < b && !data.Less(b-1, pivot); b-- { // data[b] == pivot
}
- for ; a != b && data.Less(a, pivot); a++ { // data[a] < pivot
+ for ; a < b && data.Less(a, pivot); a++ { // data[a] < pivot
}
- if a == b {
+ if a >= b {
break
}
// data[a] == pivot; data[b-1] < pivot
diff --git a/src/sort/sort_test.go b/src/sort/sort_test.go
index 6c36f30..a5da6b2 100644
--- a/src/sort/sort_test.go
+++ b/src/sort/sort_test.go
@@ -109,6 +109,43 @@ func TestReverseSortIntSlice(t *testing.T) {
}
}
+type nonDeterministicTestingData struct {
+ r *rand.Rand
+}
+
+func (t *nonDeterministicTestingData) Len() int {
+ return 500
+}
+func (t *nonDeterministicTestingData) Less(i, j int) bool {
+ if i < 0 || j < 0 || i >= t.Len() || j >= t.Len() {
+ panic("nondeterministic comparison out of bounds")
+ }
+ return t.r.Float32() < 0.5
+}
+func (t *nonDeterministicTestingData) Swap(i, j int) {
+ if i < 0 || j < 0 || i >= t.Len() || j >= t.Len() {
+ panic("nondeterministic comparison out of bounds")
+ }
+}
+
+func TestNonDeterministicComparison(t *testing.T) {
+ // Ensure that sort.Sort does not panic when Less returns inconsistent results.
+ // See https://golang.org/issue/14377.
+ defer func() {
+ if r := recover(); r != nil {
+ t.Error(r)
+ }
+ }()
+
+ td := &nonDeterministicTestingData{
+ r: rand.New(rand.NewSource(0)),
+ }
+
+ for i := 0; i < 10; i++ {
+ Sort(td)
+ }
+}
+
func BenchmarkSortString1K(b *testing.B) {
b.StopTimer()
for i := 0; i < b.N; i++ {
diff --git a/src/syscall/asm_linux_386.s b/src/syscall/asm_linux_386.s
index c940605..228a542 100644
--- a/src/syscall/asm_linux_386.s
+++ b/src/syscall/asm_linux_386.s
@@ -12,18 +12,9 @@
// func Syscall(trap uintptr, a1, a2, a3 uintptr) (r1, r2, err uintptr);
// Trap # in AX, args in BX CX DX SI DI, return in AX
-// Most linux systems use glibc's dynamic linker, which puts the
-// __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position
-// independent code and setldt in runtime does the same in the statically
-// linked case. Android, however, uses bionic's dynamic linker, which does not
-// save the helper anywhere, and so the only way to invoke a syscall from
-// position independent code is boring old int $0x80 (which is also what
-// bionic's syscall wrappers use).
-#ifdef GOOS_android
+// See ../runtime/sys_linux_386.s for the reason why we always use int 0x80
+// instead of the glibc-specific "CALL 0x10(GS)".
#define INVOKE_SYSCALL INT $0x80
-#else
-#define INVOKE_SYSCALL CALL 0x10(GS)
-#endif
TEXT ·Syscall(SB),NOSPLIT,$0-28
CALL runtime·entersyscall(SB)
diff --git a/src/syscall/types_linux.go b/src/syscall/types_linux.go
index cff4069..cb6836b 100644
--- a/src/syscall/types_linux.go
+++ b/src/syscall/types_linux.go
@@ -105,6 +105,9 @@ struct my_epoll_event {
// alignment requirements of EABI
int32_t padFd;
#endif
+#ifdef __powerpc64__
+ int32_t _padFd;
+#endif
int32_t fd;
int32_t pad;
};
diff --git a/src/syscall/ztypes_linux_ppc64.go b/src/syscall/ztypes_linux_ppc64.go
index 33d1b7f..915ca95 100644
--- a/src/syscall/ztypes_linux_ppc64.go
+++ b/src/syscall/ztypes_linux_ppc64.go
@@ -574,9 +574,10 @@ type Ustat_t struct {
}
type EpollEvent struct {
- Events uint32
- Fd int32
- Pad int32
+ Events uint32
+ X_padFd int32
+ Fd int32
+ Pad int32
}
const (
diff --git a/src/syscall/ztypes_linux_ppc64le.go b/src/syscall/ztypes_linux_ppc64le.go
index 27ca004..a118055 100644
--- a/src/syscall/ztypes_linux_ppc64le.go
+++ b/src/syscall/ztypes_linux_ppc64le.go
@@ -574,9 +574,10 @@ type Ustat_t struct {
}
type EpollEvent struct {
- Events uint32
- Fd int32
- Pad int32
+ Events uint32
+ X_padFd int32
+ Fd int32
+ Pad int32
}
const (
diff --git a/test/escape_closure.go b/test/escape_closure.go
index 4cdb06e..f36073e 100644
--- a/test/escape_closure.go
+++ b/test/escape_closure.go
@@ -145,3 +145,29 @@ func ClosureCallArgs15() {
// BAD: p should not escape here
}(&p) // ERROR "&p escapes to heap" "\(func literal\)\(&p\) escapes to heap"
}
+
+func ClosureLeak1(s string) string { // ERROR "ClosureLeak1 s does not escape"
+ t := s + "YYYY" // ERROR "escapes to heap"
+ return ClosureLeak1a(t) // ERROR "ClosureLeak1 ... argument does not escape"
+}
+
+// See #14409 -- returning part of captured var leaks it.
+func ClosureLeak1a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
+ return func() string { // ERROR "ClosureLeak1a func literal does not escape"
+ return a[0]
+ }()
+}
+
+func ClosureLeak2(s string) string { // ERROR "ClosureLeak2 s does not escape"
+ t := s + "YYYY" // ERROR "escapes to heap"
+ c := ClosureLeak2a(t) // ERROR "ClosureLeak2 ... argument does not escape"
+ return c
+}
+func ClosureLeak2a(a ...string) string { // ERROR "leaking param: a to result ~r1 level=1"
+ return ClosureLeak2b(func() string { // ERROR "ClosureLeak2a func literal does not escape"
+ return a[0]
+ })
+}
+func ClosureLeak2b(f func() string) string { // ERROR "leaking param: f to result ~r1 level=1"
+ return f()
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-golang/golang.git
More information about the pkg-golang-commits
mailing list