Commit 50e0749f authored by Russ Cox's avatar Russ Cox

[dev.cc] all: merge default (e4ab8f908aac) into dev.cc

TBR=austin
CC=golang-codereviews
https://golang.org/cl/179040044
parents 754de8d4 2b3f3790
......@@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release
1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1
bffdd0cae380ce1ccf3e98ed6b6cd53fece7ba72 go1.4rc1
......@@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com>
......
......@@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com>
Emil Hessman <c.emil.hessman@gmail.com> <emil@hessman.se>
Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com>
......@@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
Nicholas Sullivan <nicholas.sullivan@gmail.com>
Nicholas Waples <nwaples@gmail.com>
Nick Cooper <nmvc@google.com>
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
Nicolas Kaiser <nikai@nikai.net>
Nicolas Owens <mischief@offblast.org>
......
......@@ -7,10 +7,10 @@
<h2 id="introduction">Introduction to Go 1.4</h2>
<p>
The latest Go release, version 1.4, arrives as scheduled six months after 1.3
and contains only one tiny language change,
a possibly breaking change to the compiler,
a backwards-compatible simple form of <code>for</code>-<code>range</code> loop.
The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
It contains only one tiny language change,
in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
and a possibly breaking change to the compiler involving methods on pointers-to-pointers.
The release focuses primarily on implementation work, improving the garbage collector
and preparing the ground for a fully concurrent collector to be rolled out in the
next few releases.
......@@ -20,7 +20,7 @@ this release therefore eliminates the notorious "hot stack split" problem.
There are some new tools available including support in the <code>go</code> command
for build-time source code generation.
The release also adds support for ARM processors on Android and Native Client (NaCl)
and AMD64 on Plan 9.
and for AMD64 on Plan 9.
As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
of compatibility</a>,
and almost everything
......@@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change.
<ul>
<li>
The <a href="/pkg/archive/zip/"><code>archive/zip</code></a> package's
<a href="/pkg/archive/zip/#Writer"><code>Writer</code></a> now supports a
<a href="/pkg/archive/zip/#Writer.Flush"><code>Flush</code></a> method.
</li>
<li>
The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>,
<a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>,
and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a>
packages now support a <code>Reset</code> method
for the decompressors, allowing them to reuse buffers and improve performance.
The <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a> package also has a
<a href="/pkg/compress/gzip/#Reader.Multistream"><code>Multistream</code></a> method to control support
for multistream files.
</li>
<li>
The <a href="/pkg/crypto/"><code>crypto</code></a> package now has a
<a href="/pkg/crypto/#Signer"><code>Signer</code></a> interface, implemented by the
<code>PrivateKey</code> types in
<a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a> and
<a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>.
</li>
<li>
......@@ -665,6 +682,16 @@ to help clients detect fallback attacks.
those attacks.)
</li>
<li>
The <a href="/pkg/database/sql/"><code>database/sql</code></a> package can now list all registered
<a href="/pkg/database/sql/#Drivers"><code>Drivers</code></a>.
</li>
<li>
The <a href="/pkg/debug/dwarf/"><code>debug/dwarf</code></a> package now supports
<a href="/pkg/debug/dwarf/#UnspecifiedType"><code>UnspecifiedType</code></a>s.
</li>
<li>
In the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package,
optional elements with a default value will now only be omitted if they have that value.
......@@ -685,6 +712,11 @@ in some cases, especially involving arrays, it can be faster.
There is no functional change.
</li>
<li>
The <a href="/pkg/encoding/xml/"><code>encoding/xml</code></a> package's
<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> can now report its input offset.
</li>
<li>
In the <a href="/pkg/fmt/"><code>fmt</code></a> package,
formatting of pointers to maps has changed to be consistent with that of pointers
......@@ -693,6 +725,28 @@ For instance, <code>&amp;map[string]int{"one":</code> <code>1}</code> now prints
<code>&amp;map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value.
</li>
<li>
The <a href="/pkg/image/"><code>image</code></a> package's
<a href="/pkg/image/#Image"><code>Image</code></a>
implementations like
<a href="/pkg/image/#RGBA"><code>RGBA</code></a> and
<a href="/pkg/image/#Gray"><code>Gray</code></a> have specialized
<a href="/pkg/image/#RGBA.RGBAAt"><code>RGBAAt</code></a> and
<a href="/pkg/image/#Gray.GrayAt"><code>GrayAt</code></a> methods alongside the general
<a href="/pkg/image/#Image.At"><code>At</code></a> method.
</li>
<li>
The <a href="/pkg/image/png/"><code>image/png</code></a> package now has an
<a href="/pkg/image/png/#Encoder"><code>Encoder</code></a>
type to control the compression level used for encoding.
</li>
<li>
The <a href="/pkg/math/"><code>math</code></a> package now has a
<a href="/pkg/math/#Nextafter32"><code>Nextafter32</code><a/> function.
</li>
<li>
The <a href="/pkg/net/http/"><code>net/http</code></a> package's
<a href="/pkg/net/http/#Request"><code>Request</code></a> type
......@@ -721,6 +775,7 @@ The <a href="/pkg/os/"><code>os</code></a> package
now implements symbolic links on the Windows operating system
through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function.
Other operating systems already have this functionality.
There is also a new <a href="/pkg/os/#Unsetenv"><code>Unsetenv</code></a> function.
</li>
<li>
......
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of October 27, 2014",
"Subtitle": "Version of November 11, 2014",
"Path": "/ref/spec"
}-->
......@@ -2521,30 +2521,40 @@ The following rules apply to selectors:
<ol>
<li>
For a value <code>x</code> of type <code>T</code> or <code>*T</code>
where <code>T</code> is not an interface type,
where <code>T</code> is not a pointer or interface type,
<code>x.f</code> denotes the field or method at the shallowest depth
in <code>T</code> where there
is such an <code>f</code>.
If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
with shallowest depth, the selector expression is illegal.
</li>
<li>
For a variable <code>x</code> of type <code>I</code> where <code>I</code>
For a value <code>x</code> of type <code>I</code> where <code>I</code>
is an interface type, <code>x.f</code> denotes the actual method with name
<code>f</code> of the value assigned to <code>x</code>.
<code>f</code> of the dynamic value of <code>x</code>.
If there is no method with name <code>f</code> in the
<a href="#Method_sets">method set</a> of <code>I</code>, the selector
expression is illegal.
</li>
<li>
As an exception, if the type of <code>x</code> is a named pointer type
and <code>(*x).f</code> is a valid selector expression denoting a field
(but not a method), <code>x.f</code> is shorthand for <code>(*x).f</code>.
</li>
<li>
In all other cases, <code>x.f</code> is illegal.
</li>
<li>
If <code>x</code> is of pointer type and has the value
<code>nil</code> and <code>x.f</code> denotes a struct field,
assigning to or evaluating <code>x.f</code>
causes a <a href="#Run_time_panics">run-time panic</a>.
</li>
<li>
If <code>x</code> is of interface type and has the value
<code>nil</code>, <a href="#Calls">calling</a> or
......@@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
</li>
</ol>
<p>
Selectors automatically <a href="#Address_operators">dereference</a>
pointers to structs.
If <code>x</code> is a pointer to a struct, <code>x.y</code>
is shorthand for <code>(*x).y</code>; if the field <code>y</code>
is also a pointer to a struct, <code>x.y.z</code> is shorthand
for <code>(*(*x).y).z</code>, and so on.
If <code>x</code> contains an anonymous field of type <code>*A</code>,
where <code>A</code> is also a struct type,
<code>x.f</code> is shorthand for <code>(*x.A).f</code>.
</p>
<p>
For example, given the declarations:
</p>
......@@ -2574,13 +2572,13 @@ type T0 struct {
x int
}
func (recv *T0) M0()
func (*T0) M0()
type T1 struct {
y int
}
func (recv T1) M1()
func (T1) M1()
type T2 struct {
z int
......@@ -2588,9 +2586,13 @@ type T2 struct {
*T0
}
func (recv *T2) M2()
func (*T2) M2()
var p *T2 // with p != nil and p.T0 != nil
type Q *T2
var t T2 // with t.T0 != nil
var p *T2 // with p != nil and (*p).T0 != nil
var q Q = p
</pre>
<p>
......@@ -2598,13 +2600,27 @@ one may write:
</p>
<pre>
p.z // (*p).z
p.y // ((*p).T1).y
p.x // (*(*p).T0).x
t.z // t.z
t.y // t.T1.y
t.x // (*t.TO).x
p.z // (*p).z
p.y // (*p).T1.y
p.x // (*(*p).T0).x
q.x // (*(*q).T0).x (*q).x is a valid field selector
p.M2() // p.M2() M2 expects *T2 receiver
p.M1() // ((*p).T1).M1() M1 expects T1 receiver
p.M0() // ((&(*p).T0)).M0() M0 expects *T0 receiver, see section on Calls
</pre>
p.M2() // (*p).M2()
p.M1() // ((*p).T1).M1()
p.M0() // ((*p).T0).M0()
<p>
but the following is invalid:
</p>
<pre>
q.M0() // (*q).M0 is valid but not a field selector
</pre>
......
......@@ -47,7 +47,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that
<tr><td>FreeBSD 8 or later</td> <td>amd64, 386, arm</td> <td>Debian GNU/kFreeBSD not supported; FreeBSD/ARM needs FreeBSD 10 or later</td></tr>
<tr><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm</td> <td>CentOS/RHEL 5.x not supported; no binary distribution for ARM yet</td></tr>
<tr><td>Mac OS X 10.6 or later</td> <td>amd64, 386</td> <td>use the gcc<sup>&#8224;</sup> that comes with Xcode<sup>&#8225;</sup></td></tr>
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cgywin or msys.</td></tr>
<tr><td>Windows XP or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>&#8224;</sup>. No need for cygwin or msys.</td></tr>
</table>
<p>
......
......@@ -56,8 +56,8 @@ const (
blogPath = "golang.org/x/blog"
toolPath = "golang.org/x/tools"
tourPath = "code.google.com/p/go-tour"
defaultToolTag = "release-branch.go1.3"
defaultTourTag = "release-branch.go1.3"
defaultToolTag = "release-branch.go1.4"
defaultTourTag = "release-branch.go1.4"
)
// Import paths for tool commands.
......
......@@ -230,7 +230,7 @@ regopt(Prog *firstp)
/* the mod/div runtime routines smash R12 */
if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU)
r->set.b[z] |= RtoB(12);
r->set.b[0] |= RtoB(12);
}
if(firstr == R)
return;
......
......@@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array
actually requires a pointer to the first element of the array.
C compilers are aware of this calling convention and adjust
the call accordingly, but Go cannot. In Go, you must pass
the pointer to the first element explicitly: C.f(&x[0]).
the pointer to the first element explicitly: C.f(&C.x[0]).
A few special functions convert between Go and C types
by making copies of the data. In pseudo-Go definitions:
......
......@@ -7,7 +7,7 @@
package objfile
import (
"debug/goobj"
"cmd/internal/goobj"
"fmt"
"os"
)
......
......@@ -10,7 +10,7 @@
package main
import (
"debug/goobj"
"cmd/internal/goobj"
"strconv"
"strings"
)
......
......@@ -13,7 +13,7 @@ package main
import (
"bytes"
"debug/goobj"
"cmd/internal/goobj"
"testing"
)
......
......@@ -6,7 +6,7 @@
package main
import "debug/goobj"
import "cmd/internal/goobj"
// dead removes unreachable code and data from the program.
// It is basically a mark-sweep garbage collection: traverse all the
......
......@@ -5,7 +5,7 @@
package main
import (
"debug/goobj"
"cmd/internal/goobj"
"reflect"
"strings"
"testing"
......
......@@ -7,7 +7,7 @@
package main
import (
"debug/goobj"
"cmd/internal/goobj"
)
// A layoutSection describes a single section to add to the
......
......@@ -6,7 +6,7 @@ package main
import (
"bytes"
"debug/goobj"
"cmd/internal/goobj"
"io/ioutil"
"testing"
)
......
......@@ -7,7 +7,7 @@
package main
import (
"debug/goobj"
"cmd/internal/goobj"
"encoding/binary"
"os"
"sort"
......
......@@ -6,7 +6,7 @@ package main
import (
"bytes"
"debug/goobj"
"cmd/internal/goobj"
"fmt"
"math/rand"
"sort"
......
......@@ -5,7 +5,7 @@
package main
import (
"debug/goobj"
"cmd/internal/goobj"
"encoding/binary"
"fmt"
"go/build"
......
......@@ -7,7 +7,7 @@
package main
import "debug/goobj"
import "cmd/internal/goobj"
func (p *Prog) runtime() {
p.pclntab()
......
......@@ -11,7 +11,7 @@
package main
import (
"debug/goobj"
"cmd/internal/goobj"
"os"
"sort"
"strings"
......@@ -69,7 +69,7 @@ func (p *Prog) scanFile(pkgpath string, file string) {
return
}
// TODO(rsc): Change debug/goobj to record package name as gp.Name.
// TODO(rsc): Change cmd/internal/goobj to record package name as gp.Name.
// TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
pkg.Package = gp
......
......@@ -358,9 +358,13 @@ func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, stri
for {
line, err := buf.ReadString('\n')
if err != nil {
if line == "" || err != io.EOF {
if err != io.EOF {
return nil, file, err
}
if line == "" {
// end was at or past EOF; that's okay
break
}
}
if lineno >= start {
flat, cum := sumNodes(lineNodes[lineno])
......
......@@ -16,6 +16,7 @@ var certFiles = []string{
"/etc/ssl/cert.pem", // OpenBSD
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
"/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/certs/ca-certificates.crt", // Solaris 11.2+
}
// Possible directories with certificate files; stop after successfully
......
......@@ -17,8 +17,8 @@ const Size = 4
// Predefined polynomials.
const (
// Far and away the most common CRC-32 polynomial.
// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ...
// IEEE is by far and away the most common CRC-32 polynomial.
// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
IEEE = 0xedb88320
// Castagnoli's polynomial, used in iSCSI.
......
......@@ -22,8 +22,12 @@ import (
"time"
)
// A Dir implements http.FileSystem using the native file
// system restricted to a specific directory tree.
// A Dir implements FileSystem using the native file system restricted to a
// specific directory tree.
//
// While the FileSystem.Open method takes '/'-separated paths, a Dir's string
// value is a filename on the native file system, not a URL, so it is separated
// by filepath.Separator, which isn't necessarily '/'.
//
// An empty Dir is treated as ".".
type Dir string
......
......@@ -7,7 +7,10 @@ package url_test
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)
func ExampleValues() {
......@@ -39,3 +42,30 @@ func ExampleURL() {
fmt.Println(u)
// Output: https://google.com/search?q=golang
}
func ExampleURL_opaque() {
// Sending a literal '%' in an HTTP request's Path
req := &http.Request{
Method: "GET",
Host: "example.com", // takes precendence over URL.Host
URL: &url.URL{
Host: "ignored",
Scheme: "https",
Opaque: "/%2f/",
},
Header: http.Header{
"User-Agent": {"godoc-example/0.1"},
},
}
out, err := httputil.DumpRequestOut(req, true)
if err != nil {
log.Fatal(err)
}
fmt.Println(strings.Replace(string(out), "\r", "", -1))
// Output:
// GET /%2f/ HTTP/1.1
// Host: example.com
// User-Agent: godoc-example/0.1
// Accept-Encoding: gzip
//
}
......@@ -39,7 +39,7 @@ const (
OpEmptyMatch // matches empty string
OpLiteral // matches Runes sequence
OpCharClass // matches Runes interpreted as range pair list
OpAnyCharNotNL // matches any character
OpAnyCharNotNL // matches any character except newline
OpAnyChar // matches any character
OpBeginLine // matches empty string at beginning of line
OpEndLine // matches empty string at end of line
......
......@@ -64,17 +64,6 @@ echo
echo '# sync -cpu=10'
go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -cpu=10
# Race detector only supported on Linux, FreeBSD and OS X,
# and only on amd64, and only when cgo is enabled.
case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
echo
echo '# Testing race detector.'
go test -race -i runtime/race flag
go test -race -run=Output runtime/race
go test -race -short flag
esac
xcd() {
echo
echo '#' $1
......@@ -120,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
[ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/test
# cgo tests inspect the traceback for runtime functions
extlink=0
export GOTRACEBACK=2
go test -ldflags '-linkmode=auto' || exit 1
# linkmode=internal fails on dragonfly since errno is a TLS relocation.
......@@ -128,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
openbsd-386 | openbsd-amd64)
# test linkmode=external, but __thread not supported, so skip testtls.
go test -ldflags '-linkmode=external' || exit 1
extlink=1
;;
darwin-386 | darwin-amd64)
# linkmode=external fails on OS X 10.6 and earlier == Darwin
# 10.8 and earlier.
case $(uname -r) in
[0-9].* | 10.*) ;;
*) go test -ldflags '-linkmode=external' || exit 1;;
*)
go test -ldflags '-linkmode=external' || exit 1
extlink=1
;;
esac
;;
android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64)
go test -ldflags '-linkmode=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1
extlink=1
case "$GOHOSTOS-$GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking
......@@ -164,6 +159,23 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr
esac
) || exit $?
# Race detector only supported on Linux, FreeBSD and OS X,
# and only on amd64, and only when cgo is enabled.
# Delayed until here so we know whether to try external linking.
case "$GOHOSTOS-$GOOS-$GOARCH-$CGO_ENABLED" in
linux-linux-amd64-1 | freebsd-freebsd-amd64-1 | darwin-darwin-amd64-1)
echo
echo '# Testing race detector.'
go test -race -i runtime/race flag os/exec
go test -race -run=Output runtime/race
go test -race -short flag os/exec
# Test with external linking; see issue 9133.
if [ "$extlink" = 1 ]; then
go test -race -short -ldflags=-linkmode=external flag os/exec
fi
esac
# This tests cgo -cdefs. That mode is not supported,
# so it's okay if it doesn't work on some systems.
# In particular, it works badly with clang on OS X.
......
......@@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog {
return nil
}
q.first = sgp.next
sgp.next = nil
if q.last == sgp {
q.last = nil
}
......
......@@ -7,7 +7,7 @@
// finalizers, etc.) to a file.
// The format of the dumped file is described at
// http://code.google.com/p/go-wiki/wiki/heapdump14
// http://golang.org/s/go14heapdump.
package runtime
......
......@@ -477,6 +477,8 @@ func GC() {
// linker-provided
var noptrdata struct{}
var enoptrdata struct{}
var noptrbss struct{}
var enoptrbss struct{}
// SetFinalizer sets the finalizer associated with x to f.
......@@ -553,8 +555,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
// func main() {
// runtime.SetFinalizer(Foo, nil)
// }
// The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss.
if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
// The relevant segments are: noptrdata, data, bss, noptrbss.
// We cannot assume they are in any order or even contiguous,
// due to external linking.
if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
return
}
gothrow("runtime.SetFinalizer: pointer not in allocated block")
......
......@@ -51,10 +51,26 @@ func clearpools() {
if c := p.mcache; c != nil {
c.tiny = nil
c.tinysize = 0
// disconnect cached list before dropping it on the floor,
// so that a dangling ref to one entry does not pin all of them.
var sg, sgnext *sudog
for sg = c.sudogcache; sg != nil; sg = sgnext {
sgnext = sg.next
sg.next = nil
}
c.sudogcache = nil
}
// clear defer pools
for i := range p.deferpool {
// disconnect cached list before dropping it on the floor,
// so that a dangling ref to one entry does not pin all of them.
var d, dlink *_defer
for d = p.deferpool[i]; d != nil; d = dlink {
dlink = d.link
d.link = nil
}
p.deferpool[i] = nil
}
}
......
......@@ -165,6 +165,7 @@ func acquireSudog() *sudog {
gothrow("acquireSudog: found s.elem != nil in cache")
}
c.sudogcache = s.next
s.next = nil
return s
}
......@@ -190,6 +191,15 @@ func releaseSudog(s *sudog) {
if s.selectdone != nil {
gothrow("runtime: sudog with non-nil selectdone")
}
if s.next != nil {
gothrow("runtime: sudog with non-nil next")
}
if s.prev != nil {
gothrow("runtime: sudog with non-nil prev")
}
if s.waitlink != nil {
gothrow("runtime: sudog with non-nil waitlink")
}
gp := getg()
if gp.param != nil {
gothrow("runtime: releaseSudog with non-nil gp.param")
......
// Copyright 2014 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 race
// +build darwin freebsd linux
package race_test
import (
"sync/atomic"
"syscall"
"testing"
"unsafe"
)
// Test that race detector does not crash when accessing non-Go allocated memory (issue 9136).
func TestNonGoMemory(t *testing.T) {
data, err := syscall.Mmap(-1, 0, 4096, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANON|syscall.MAP_PRIVATE)
if err != nil {
t.Fatalf("failed to mmap memory: %v", err)
}
p := (*uint32)(unsafe.Pointer(&data[0]))
atomic.AddUint32(p, 1)
(*p)++
if *p != 2 {
t.Fatalf("data[0] = %v, expect 2", *p)
}
syscall.Munmap(data)
}
......@@ -81,6 +81,10 @@ var __tsan_go_ignore_sync_end byte
//go:cgo_import_static __tsan_go_atomic32_compare_exchange
//go:cgo_import_static __tsan_go_atomic64_compare_exchange
// start/end of global data (data+bss).
var racedatastart uintptr
var racedataend uintptr
// start/end of heap for race_amd64.s
var racearenastart uintptr
var racearenaend uintptr
......@@ -99,7 +103,7 @@ func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
//go:nosplit
func isvalidaddr(addr unsafe.Pointer) bool {
return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend ||
uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(addr) && uintptr(addr) < uintptr(unsafe.Pointer(&enoptrbss))
racedatastart <= uintptr(addr) && uintptr(addr) < racedataend
}
//go:nosplit
......@@ -113,9 +117,36 @@ func raceinit() uintptr {
racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
// Round data segment to page boundaries, because it's used in mmap().
start := uintptr(unsafe.Pointer(&noptrdata)) &^ (_PageSize - 1)
size := round(uintptr(unsafe.Pointer(&enoptrbss))-start, _PageSize)
start := ^uintptr(0)
end := uintptr(0)
if start > uintptr(unsafe.Pointer(&noptrdata)) {
start = uintptr(unsafe.Pointer(&noptrdata))
}
if start > uintptr(unsafe.Pointer(&data)) {
start = uintptr(unsafe.Pointer(&data))
}
if start > uintptr(unsafe.Pointer(&noptrbss)) {
start = uintptr(unsafe.Pointer(&noptrbss))
}
if start > uintptr(unsafe.Pointer(&bss)) {
start = uintptr(unsafe.Pointer(&bss))
}
if end < uintptr(unsafe.Pointer(&enoptrdata)) {
end = uintptr(unsafe.Pointer(&enoptrdata))
}
if end < uintptr(unsafe.Pointer(&edata)) {
end = uintptr(unsafe.Pointer(&edata))
}
if end < uintptr(unsafe.Pointer(&enoptrbss)) {
end = uintptr(unsafe.Pointer(&enoptrbss))
}
if end < uintptr(unsafe.Pointer(&ebss)) {
end = uintptr(unsafe.Pointer(&ebss))
}
size := round(end-start, _PageSize)
racecall(&__tsan_map_shadow, start, size, 0, 0)
racedatastart = start
racedataend = start + size
return racectx
}
......
......@@ -139,17 +139,15 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0
get_tls(R12)
MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context
// Check that addr is within [arenastart, arenaend) or within [noptrdata, enoptrbss).
// Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
CMPQ RARG1, runtime·racearenastart(SB)
JB data
CMPQ RARG1, runtime·racearenaend(SB)
JB call
data:
MOVQ $runtime·noptrdata(SB), R13
CMPQ RARG1, R13
CMPQ RARG1, runtime·racedatastart(SB)
JB ret
MOVQ $runtime·enoptrbss(SB), R13
CMPQ RARG1, R13
CMPQ RARG1, runtime·racedataend(SB)
JAE ret
call:
MOVQ AX, AX // w/o this 6a miscompiles this function
......@@ -167,6 +165,7 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
MOVQ callpc+0(FP), RARG1
// void __tsan_func_enter(ThreadState *thr, void *pc);
MOVQ $__tsan_func_enter(SB), AX
// racecall<> preserves R15
CALL racecall<>(SB)
MOVQ R15, DX // restore function entry context
RET
......@@ -307,13 +306,45 @@ TEXT sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0
TEXT racecallatomic<>(SB), NOSPLIT, $0-0
// Trigger SIGSEGV early.
MOVQ 16(SP), R12
MOVL (R12), R12
MOVL (R12), R13
// Check that addr is within [arenastart, arenaend) or within [racedatastart, racedataend).
CMPQ R12, runtime·racearenastart(SB)
JB racecallatomic_data
CMPQ R12, runtime·racearenaend(SB)
JB racecallatomic_ok
racecallatomic_data:
CMPQ R12, runtime·racedatastart(SB)
JB racecallatomic_ignore
CMPQ R12, runtime·racedataend(SB)
JAE racecallatomic_ignore
racecallatomic_ok:
// Addr is within the good range, call the atomic function.
get_tls(R12)
MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context
MOVQ 8(SP), RARG1 // caller pc
MOVQ (SP), RARG2 // pc
LEAQ 16(SP), RARG3 // arguments
JMP racecall<>(SB) // does not return
racecallatomic_ignore:
// Addr is outside the good range.
// Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op.
// An attempt to synchronize on the address would cause crash.
MOVQ AX, R15 // remember the original function
MOVQ $__tsan_go_ignore_sync_begin(SB), AX
MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context
CALL racecall<>(SB)
MOVQ R15, AX // restore the original function
// Call the atomic function.
MOVQ g_racectx(R14), RARG0 // goroutine context
MOVQ 8(SP), RARG1 // caller pc
MOVQ (SP), RARG2 // pc
LEAQ 16(SP), RARG3 // arguments
CALL racecall<>(SB)
// Call __tsan_go_ignore_sync_end.
MOVQ $__tsan_go_ignore_sync_end(SB), AX
MOVQ g_racectx(R14), RARG0 // goroutine context
JMP racecall<>(SB)
// void runtime·racecall(void(*f)(...), ...)
......
......@@ -404,6 +404,7 @@ loop:
}
}
sgnext = sglist.waitlink
sglist.waitlink = nil
releaseSudog(sglist)
sglist = sgnext
}
......@@ -641,6 +642,7 @@ func (q *waitq) dequeueSudoG(s *sudog) {
if q.last == sgp {
q.last = prevsgp
}
s.next = nil
return
}
l = &sgp.next
......
......@@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) {
}
unlock(&s.lock)
if wake != nil {
wake.next = nil
goready(wake.g)
}
} else {
......@@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) {
if wake.releasetime != 0 {
wake.releasetime = cputicks()
}
wake.next = nil
goready(wake.g)
n--
}
......
......@@ -154,7 +154,7 @@ func setcallerpc(argp unsafe.Pointer, pc uintptr)
//
// func f(arg1, arg2, arg3 int) {
// pc := getcallerpc(unsafe.Pointer(&arg1))
// sp := getcallerpc(unsafe.Pointer(&arg2))
// sp := getcallersp(unsafe.Pointer(&arg1))
// }
//
// These two lines find the PC and SP immediately following
......
......@@ -19,8 +19,6 @@ type SysProcAttr struct {
Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
Setctty bool // Set controlling terminal to fd 0
Noctty bool // Detach fd 0 from controlling terminal
Foreground bool // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
Joinpgrp int // If != 0, child's process group ID. (Setpgid must not be set)
}
// Implemented in runtime package.
......@@ -81,22 +79,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
if r1 != 0 {
// parent; return PID
runtime_AfterFork()
pid = int(r1)
if sys.Joinpgrp != 0 {
// Place the child in the specified process group.
RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
} else if sys.Foreground || sys.Setpgid {
// Place the child in a new process group.
RawSyscall(SYS_SETPGID, 0, 0, 0)
if sys.Foreground {
// Set new foreground process group.
RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
}
}
return pid, 0
return int(r1), 0
}
// Fork succeeded, now in child.
......@@ -118,30 +101,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
// Set process group
if sys.Joinpgrp != 0 {
// Place the child in the specified process group.
_, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
if err1 != 0 {
goto childerror
}
} else if sys.Foreground || sys.Setpgid {
// Place the child in a new process group.
if sys.Setpgid {
_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
if err1 != 0 {
goto childerror
}
if sys.Foreground {
r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
pid := int(r1)
// Set new foreground process group.
_, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
if err1 != 0 {
goto childerror
}
}
}
// Chroot
......
......@@ -29,8 +29,6 @@ type SysProcAttr struct {
Ctty int // Controlling TTY fd (Linux only)
Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
Cloneflags uintptr // Flags for clone calls (Linux only)
Foreground bool // Set foreground process group to child's pid. (Implies Setpgid. Stdin should be a TTY)
Joinpgrp int // If != 0, child's process group ID. (Setpgid must not be set)
UidMappings []SysProcIDMap // User ID mappings for user namespaces.
GidMappings []SysProcIDMap // Group ID mappings for user namespaces.
}
......@@ -105,19 +103,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
Close(p[1])
}
if sys.Joinpgrp != 0 {
// Place the child in the specified process group.
RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
} else if sys.Foreground || sys.Setpgid {
// Place the child in a new process group.
RawSyscall(SYS_SETPGID, 0, 0, 0)
if sys.Foreground {
// Set new foreground process group.
RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
}
}
return pid, 0
}
......@@ -179,30 +164,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
}
// Set process group
if sys.Joinpgrp != 0 {
// Place the child in the specified process group.
_, _, err1 = RawSyscall(SYS_SETPGID, r1, uintptr(sys.Joinpgrp), 0)
if err1 != 0 {
goto childerror
}
} else if sys.Foreground || sys.Setpgid {
// Place the child in a new process group.
if sys.Setpgid {
_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
if err1 != 0 {
goto childerror
}
if sys.Foreground {
r1, _, _ = RawSyscall(SYS_GETPID, 0, 0, 0)
pid := int(r1)
// Set new foreground process group.
_, _, err1 = RawSyscall(SYS_IOCTL, uintptr(Stdin), TIOCSPGRP, uintptr(unsafe.Pointer(&pid)))
if err1 != 0 {
goto childerror
}
}
}
// Chroot
......
// run
// Copyright 2014 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.
// Scenario that used to leak arbitrarily many SudoG structs.
// See golang.org/issue/9110.
package main
import (
"runtime"
"runtime/debug"
"sync"
"time"
)
func main() {
debug.SetGCPercent(1000000) // only GC when we ask for GC
var stats, stats1, stats2 runtime.MemStats
release := func() {}
for i := 0; i < 20; i++ {
if i == 10 {
// Should be warmed up by now.
runtime.ReadMemStats(&stats1)
}
c := make(chan int)
for i := 0; i < 10; i++ {
go func() {
select {
case <-c:
case <-c:
case <-c:
}
}()
}
time.Sleep(1 * time.Millisecond)
release()
close(c) // let select put its sudog's into the cache
time.Sleep(1 * time.Millisecond)
// pick up top sudog
var cond1 sync.Cond
var mu1 sync.Mutex
cond1.L = &mu1
go func() {
mu1.Lock()
cond1.Wait()
mu1.Unlock()
}()
time.Sleep(1 * time.Millisecond)
// pick up next sudog
var cond2 sync.Cond
var mu2 sync.Mutex
cond2.L = &mu2
go func() {
mu2.Lock()
cond2.Wait()
mu2.Unlock()
}()
time.Sleep(1 * time.Millisecond)
// put top sudog back
cond1.Broadcast()
time.Sleep(1 * time.Millisecond)
// drop cache on floor
runtime.GC()
// release cond2 after select has gotten to run
release = func() {
cond2.Broadcast()
time.Sleep(1 * time.Millisecond)
}
}
runtime.GC()
runtime.ReadMemStats(&stats2)
if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak
print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n")
}
}
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