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 ...@@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3 f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3
f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release
1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1 1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1
bffdd0cae380ce1ccf3e98ed6b6cd53fece7ba72 go1.4rc1
...@@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com> ...@@ -145,7 +145,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com> Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com> Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.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> Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com> Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com> Eric Milliken <emilliken@gmail.com>
......
...@@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com> ...@@ -214,7 +214,7 @@ Egon Elbre <egonelbre@gmail.com>
Ehren Kret <ehren.kret@gmail.com> Ehren Kret <ehren.kret@gmail.com>
Eivind Uggedal <eivind@uggedal.com> Eivind Uggedal <eivind@uggedal.com>
Elias Naur <elias.naur@gmail.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> Eoghan Sherry <ejsherry@gmail.com>
Eric Clark <zerohp@gmail.com> Eric Clark <zerohp@gmail.com>
Eric Milliken <emilliken@gmail.com> Eric Milliken <emilliken@gmail.com>
...@@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com> ...@@ -452,6 +452,7 @@ Nicholas Katsaros <nick@nickkatsaros.com>
Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com> Nicholas Presta <nick@nickpresta.ca> <nick1presta@gmail.com>
Nicholas Sullivan <nicholas.sullivan@gmail.com> Nicholas Sullivan <nicholas.sullivan@gmail.com>
Nicholas Waples <nwaples@gmail.com> Nicholas Waples <nwaples@gmail.com>
Nick Cooper <nmvc@google.com>
Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com> Nick Craig-Wood <nick@craig-wood.com> <nickcw@gmail.com>
Nicolas Kaiser <nikai@nikai.net> Nicolas Kaiser <nikai@nikai.net>
Nicolas Owens <mischief@offblast.org> Nicolas Owens <mischief@offblast.org>
......
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
<h2 id="introduction">Introduction to Go 1.4</h2> <h2 id="introduction">Introduction to Go 1.4</h2>
<p> <p>
The latest Go release, version 1.4, arrives as scheduled six months after 1.3 The latest Go release, version 1.4, arrives as scheduled six months after 1.3.
and contains only one tiny language change, It contains only one tiny language change,
a possibly breaking change to the compiler, in the form of a backwards-compatible simple variant of <code>for</code>-<code>range</code> loop,
a backwards-compatible simple form 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 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 and preparing the ground for a fully concurrent collector to be rolled out in the
next few releases. next few releases.
...@@ -20,7 +20,7 @@ this release therefore eliminates the notorious "hot stack split" problem. ...@@ -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 There are some new tools available including support in the <code>go</code> command
for build-time source code generation. for build-time source code generation.
The release also adds support for ARM processors on Android and Native Client (NaCl) 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 As always, Go 1.4 keeps the <a href="/doc/go1compat.html">promise
of compatibility</a>, of compatibility</a>,
and almost everything and almost everything
...@@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change. ...@@ -637,12 +637,29 @@ See the relevant package documentation for more information about each change.
<ul> <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> <li>
The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>, The <a href="/pkg/compress/flate/"><code>compress/flate</code></a>,
<a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>, <a href="/pkg/compress/gzip/"><code>compress/gzip</code></a>,
and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a> and <a href="/pkg/compress/zlib/"><code>compress/zlib</code></a>
packages now support a <code>Reset</code> method packages now support a <code>Reset</code> method
for the decompressors, allowing them to reuse buffers and improve performance. 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>
<li> <li>
...@@ -665,6 +682,16 @@ to help clients detect fallback attacks. ...@@ -665,6 +682,16 @@ to help clients detect fallback attacks.
those attacks.) those attacks.)
</li> </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> <li>
In the <a href="/pkg/encoding/asn1/"><code>encoding/asn1</code></a> package, 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. 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. ...@@ -685,6 +712,11 @@ in some cases, especially involving arrays, it can be faster.
There is no functional change. There is no functional change.
</li> </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> <li>
In the <a href="/pkg/fmt/"><code>fmt</code></a> package, 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 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 ...@@ -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. <code>&amp;map[one:</code> <code>1]</code> rather than as a hexadecimal pointer value.
</li> </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> <li>
The <a href="/pkg/net/http/"><code>net/http</code></a> package's The <a href="/pkg/net/http/"><code>net/http</code></a> package's
<a href="/pkg/net/http/#Request"><code>Request</code></a> type <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 ...@@ -721,6 +775,7 @@ The <a href="/pkg/os/"><code>os</code></a> package
now implements symbolic links on the Windows operating system now implements symbolic links on the Windows operating system
through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function. through the <a href="/pkg/os/#Symlink"><code>Symlink</code></a> function.
Other operating systems already have this functionality. Other operating systems already have this functionality.
There is also a new <a href="/pkg/os/#Unsetenv"><code>Unsetenv</code></a> function.
</li> </li>
<li> <li>
......
<!--{ <!--{
"Title": "The Go Programming Language Specification", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of October 27, 2014", "Subtitle": "Version of November 11, 2014",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
...@@ -2521,30 +2521,40 @@ The following rules apply to selectors: ...@@ -2521,30 +2521,40 @@ The following rules apply to selectors:
<ol> <ol>
<li> <li>
For a value <code>x</code> of type <code>T</code> or <code>*T</code> 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 <code>x.f</code> denotes the field or method at the shallowest depth
in <code>T</code> where there in <code>T</code> where there
is such an <code>f</code>. is such an <code>f</code>.
If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a> If there is not exactly <a href="#Uniqueness_of_identifiers">one <code>f</code></a>
with shallowest depth, the selector expression is illegal. with shallowest depth, the selector expression is illegal.
</li> </li>
<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 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 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 <a href="#Method_sets">method set</a> of <code>I</code>, the selector
expression is illegal. expression is illegal.
</li> </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> <li>
In all other cases, <code>x.f</code> is illegal. In all other cases, <code>x.f</code> is illegal.
</li> </li>
<li> <li>
If <code>x</code> is of pointer type and has the value If <code>x</code> is of pointer type and has the value
<code>nil</code> and <code>x.f</code> denotes a struct field, <code>nil</code> and <code>x.f</code> denotes a struct field,
assigning to or evaluating <code>x.f</code> assigning to or evaluating <code>x.f</code>
causes a <a href="#Run_time_panics">run-time panic</a>. causes a <a href="#Run_time_panics">run-time panic</a>.
</li> </li>
<li> <li>
If <code>x</code> is of interface type and has the value If <code>x</code> is of interface type and has the value
<code>nil</code>, <a href="#Calls">calling</a> or <code>nil</code>, <a href="#Calls">calling</a> or
...@@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>. ...@@ -2553,18 +2563,6 @@ causes a <a href="#Run_time_panics">run-time panic</a>.
</li> </li>
</ol> </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> <p>
For example, given the declarations: For example, given the declarations:
</p> </p>
...@@ -2574,13 +2572,13 @@ type T0 struct { ...@@ -2574,13 +2572,13 @@ type T0 struct {
x int x int
} }
func (recv *T0) M0() func (*T0) M0()
type T1 struct { type T1 struct {
y int y int
} }
func (recv T1) M1() func (T1) M1()
type T2 struct { type T2 struct {
z int z int
...@@ -2588,9 +2586,13 @@ type T2 struct { ...@@ -2588,9 +2586,13 @@ type T2 struct {
*T0 *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> </pre>
<p> <p>
...@@ -2598,13 +2600,27 @@ one may write: ...@@ -2598,13 +2600,27 @@ one may write:
</p> </p>
<pre> <pre>
p.z // (*p).z t.z // t.z
p.y // ((*p).T1).y t.y // t.T1.y
p.x // (*(*p).T0).x 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>
p.M1() // ((*p).T1).M1() but the following is invalid:
p.M0() // ((*p).T0).M0() </p>
<pre>
q.M0() // (*q).M0 is valid but not a field selector
</pre> </pre>
......
...@@ -47,7 +47,7 @@ proceeding. If your OS or architecture is not on the list, it's possible that ...@@ -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>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>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>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> </table>
<p> <p>
......
...@@ -56,8 +56,8 @@ const ( ...@@ -56,8 +56,8 @@ const (
blogPath = "golang.org/x/blog" blogPath = "golang.org/x/blog"
toolPath = "golang.org/x/tools" toolPath = "golang.org/x/tools"
tourPath = "code.google.com/p/go-tour" tourPath = "code.google.com/p/go-tour"
defaultToolTag = "release-branch.go1.3" defaultToolTag = "release-branch.go1.4"
defaultTourTag = "release-branch.go1.3" defaultTourTag = "release-branch.go1.4"
) )
// Import paths for tool commands. // Import paths for tool commands.
......
...@@ -230,7 +230,7 @@ regopt(Prog *firstp) ...@@ -230,7 +230,7 @@ regopt(Prog *firstp)
/* the mod/div runtime routines smash R12 */ /* the mod/div runtime routines smash R12 */
if(p->as == ADIV || p->as == ADIVU || p->as == AMOD || p->as == AMODU) 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) if(firstr == R)
return; return;
......
...@@ -152,7 +152,7 @@ In C, a function argument written as a fixed size array ...@@ -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. actually requires a pointer to the first element of the array.
C compilers are aware of this calling convention and adjust C compilers are aware of this calling convention and adjust
the call accordingly, but Go cannot. In Go, you must pass 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 A few special functions convert between Go and C types
by making copies of the data. In pseudo-Go definitions: by making copies of the data. In pseudo-Go definitions:
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
package objfile package objfile
import ( import (
"debug/goobj" "cmd/internal/goobj"
"fmt" "fmt"
"os" "os"
) )
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
package main package main
import ( import (
"debug/goobj" "cmd/internal/goobj"
"strconv" "strconv"
"strings" "strings"
) )
......
...@@ -13,7 +13,7 @@ package main ...@@ -13,7 +13,7 @@ package main
import ( import (
"bytes" "bytes"
"debug/goobj" "cmd/internal/goobj"
"testing" "testing"
) )
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
package main package main
import "debug/goobj" import "cmd/internal/goobj"
// dead removes unreachable code and data from the program. // dead removes unreachable code and data from the program.
// It is basically a mark-sweep garbage collection: traverse all the // It is basically a mark-sweep garbage collection: traverse all the
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package main package main
import ( import (
"debug/goobj" "cmd/internal/goobj"
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
package main package main
import ( import (
"debug/goobj" "cmd/internal/goobj"
) )
// A layoutSection describes a single section to add to the // A layoutSection describes a single section to add to the
......
...@@ -6,7 +6,7 @@ package main ...@@ -6,7 +6,7 @@ package main
import ( import (
"bytes" "bytes"
"debug/goobj" "cmd/internal/goobj"
"io/ioutil" "io/ioutil"
"testing" "testing"
) )
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
package main package main
import ( import (
"debug/goobj" "cmd/internal/goobj"
"encoding/binary" "encoding/binary"
"os" "os"
"sort" "sort"
......
...@@ -6,7 +6,7 @@ package main ...@@ -6,7 +6,7 @@ package main
import ( import (
"bytes" "bytes"
"debug/goobj" "cmd/internal/goobj"
"fmt" "fmt"
"math/rand" "math/rand"
"sort" "sort"
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
package main package main
import ( import (
"debug/goobj" "cmd/internal/goobj"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"go/build" "go/build"
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
package main package main
import "debug/goobj" import "cmd/internal/goobj"
func (p *Prog) runtime() { func (p *Prog) runtime() {
p.pclntab() p.pclntab()
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
package main package main
import ( import (
"debug/goobj" "cmd/internal/goobj"
"os" "os"
"sort" "sort"
"strings" "strings"
...@@ -69,7 +69,7 @@ func (p *Prog) scanFile(pkgpath string, file string) { ...@@ -69,7 +69,7 @@ func (p *Prog) scanFile(pkgpath string, file string) {
return 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". // TODO(rsc): If pkgpath == "main", check that gp.Name == "main".
pkg.Package = gp pkg.Package = gp
......
...@@ -358,9 +358,13 @@ func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, stri ...@@ -358,9 +358,13 @@ func getFunctionSource(fun, file string, fns nodes, start, end int) (nodes, stri
for { for {
line, err := buf.ReadString('\n') line, err := buf.ReadString('\n')
if err != nil { if err != nil {
if line == "" || err != io.EOF { if err != io.EOF {
return nil, file, err return nil, file, err
} }
if line == "" {
// end was at or past EOF; that's okay
break
}
} }
if lineno >= start { if lineno >= start {
flat, cum := sumNodes(lineNodes[lineno]) flat, cum := sumNodes(lineNodes[lineno])
......
...@@ -16,6 +16,7 @@ var certFiles = []string{ ...@@ -16,6 +16,7 @@ var certFiles = []string{
"/etc/ssl/cert.pem", // OpenBSD "/etc/ssl/cert.pem", // OpenBSD
"/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly "/usr/local/share/certs/ca-root-nss.crt", // FreeBSD/DragonFly
"/etc/pki/tls/cacert.pem", // OpenELEC "/etc/pki/tls/cacert.pem", // OpenELEC
"/etc/certs/ca-certificates.crt", // Solaris 11.2+
} }
// Possible directories with certificate files; stop after successfully // Possible directories with certificate files; stop after successfully
......
...@@ -17,8 +17,8 @@ const Size = 4 ...@@ -17,8 +17,8 @@ const Size = 4
// Predefined polynomials. // Predefined polynomials.
const ( const (
// Far and away the most common CRC-32 polynomial. // IEEE is by far and away the most common CRC-32 polynomial.
// Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, mpeg-2, ... // Used by ethernet (IEEE 802.3), v.42, fddi, gzip, zip, png, ...
IEEE = 0xedb88320 IEEE = 0xedb88320
// Castagnoli's polynomial, used in iSCSI. // Castagnoli's polynomial, used in iSCSI.
......
...@@ -22,8 +22,12 @@ import ( ...@@ -22,8 +22,12 @@ import (
"time" "time"
) )
// A Dir implements http.FileSystem using the native file // A Dir implements FileSystem using the native file system restricted to a
// system restricted to a specific directory tree. // 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 ".". // An empty Dir is treated as ".".
type Dir string type Dir string
......
...@@ -7,7 +7,10 @@ package url_test ...@@ -7,7 +7,10 @@ package url_test
import ( import (
"fmt" "fmt"
"log" "log"
"net/http"
"net/http/httputil"
"net/url" "net/url"
"strings"
) )
func ExampleValues() { func ExampleValues() {
...@@ -39,3 +42,30 @@ func ExampleURL() { ...@@ -39,3 +42,30 @@ func ExampleURL() {
fmt.Println(u) fmt.Println(u)
// Output: https://google.com/search?q=golang // 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 ( ...@@ -39,7 +39,7 @@ const (
OpEmptyMatch // matches empty string OpEmptyMatch // matches empty string
OpLiteral // matches Runes sequence OpLiteral // matches Runes sequence
OpCharClass // matches Runes interpreted as range pair list OpCharClass // matches Runes interpreted as range pair list
OpAnyCharNotNL // matches any character OpAnyCharNotNL // matches any character except newline
OpAnyChar // matches any character OpAnyChar // matches any character
OpBeginLine // matches empty string at beginning of line OpBeginLine // matches empty string at beginning of line
OpEndLine // matches empty string at end of line OpEndLine // matches empty string at end of line
......
...@@ -64,17 +64,6 @@ echo ...@@ -64,17 +64,6 @@ echo
echo '# sync -cpu=10' echo '# sync -cpu=10'
go test sync -short -timeout=$(expr 120 \* $timeout_scale)s -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() { xcd() {
echo echo
echo '#' $1 echo '#' $1
...@@ -120,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1 ...@@ -120,6 +109,7 @@ go run $GOROOT/test/run.go - . || exit 1
[ "$CGO_ENABLED" != 1 ] || [ "$CGO_ENABLED" != 1 ] ||
(xcd ../misc/cgo/test (xcd ../misc/cgo/test
# cgo tests inspect the traceback for runtime functions # cgo tests inspect the traceback for runtime functions
extlink=0
export GOTRACEBACK=2 export GOTRACEBACK=2
go test -ldflags '-linkmode=auto' || exit 1 go test -ldflags '-linkmode=auto' || exit 1
# linkmode=internal fails on dragonfly since errno is a TLS relocation. # linkmode=internal fails on dragonfly since errno is a TLS relocation.
...@@ -128,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in ...@@ -128,19 +118,24 @@ case "$GOHOSTOS-$GOARCH" in
openbsd-386 | openbsd-amd64) openbsd-386 | openbsd-amd64)
# test linkmode=external, but __thread not supported, so skip testtls. # test linkmode=external, but __thread not supported, so skip testtls.
go test -ldflags '-linkmode=external' || exit 1 go test -ldflags '-linkmode=external' || exit 1
extlink=1
;; ;;
darwin-386 | darwin-amd64) darwin-386 | darwin-amd64)
# linkmode=external fails on OS X 10.6 and earlier == Darwin # linkmode=external fails on OS X 10.6 and earlier == Darwin
# 10.8 and earlier. # 10.8 and earlier.
case $(uname -r) in case $(uname -r) in
[0-9].* | 10.*) ;; [0-9].* | 10.*) ;;
*) go test -ldflags '-linkmode=external' || exit 1;; *)
go test -ldflags '-linkmode=external' || exit 1
extlink=1
;;
esac esac
;; ;;
android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | freebsd-arm | linux-386 | linux-amd64 | linux-arm | netbsd-386 | netbsd-amd64) 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=external' || exit 1
go test -ldflags '-linkmode=auto' ../testtls || exit 1 go test -ldflags '-linkmode=auto' ../testtls || exit 1
go test -ldflags '-linkmode=external' ../testtls || exit 1 go test -ldflags '-linkmode=external' ../testtls || exit 1
extlink=1
case "$GOHOSTOS-$GOARCH" in case "$GOHOSTOS-$GOARCH" in
netbsd-386 | netbsd-amd64) ;; # no static linking netbsd-386 | netbsd-amd64) ;; # no static linking
...@@ -164,6 +159,23 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr ...@@ -164,6 +159,23 @@ android-arm | dragonfly-386 | dragonfly-amd64 | freebsd-386 | freebsd-amd64 | fr
esac esac
) || exit $? ) || 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, # This tests cgo -cdefs. That mode is not supported,
# so it's okay if it doesn't work on some systems. # so it's okay if it doesn't work on some systems.
# In particular, it works badly with clang on OS X. # In particular, it works badly with clang on OS X.
......
...@@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog { ...@@ -630,6 +630,7 @@ func (q *waitq) dequeue() *sudog {
return nil return nil
} }
q.first = sgp.next q.first = sgp.next
sgp.next = nil
if q.last == sgp { if q.last == sgp {
q.last = nil q.last = nil
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
// finalizers, etc.) to a file. // finalizers, etc.) to a file.
// The format of the dumped file is described at // 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 package runtime
......
...@@ -477,6 +477,8 @@ func GC() { ...@@ -477,6 +477,8 @@ func GC() {
// linker-provided // linker-provided
var noptrdata struct{} var noptrdata struct{}
var enoptrdata struct{}
var noptrbss struct{}
var enoptrbss struct{} var enoptrbss struct{}
// SetFinalizer sets the finalizer associated with x to f. // SetFinalizer sets the finalizer associated with x to f.
...@@ -553,8 +555,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) { ...@@ -553,8 +555,13 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
// func main() { // func main() {
// runtime.SetFinalizer(Foo, nil) // runtime.SetFinalizer(Foo, nil)
// } // }
// The segments are, in order: text, rodata, noptrdata, data, bss, noptrbss. // The relevant segments are: noptrdata, data, bss, noptrbss.
if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) { // 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 return
} }
gothrow("runtime.SetFinalizer: pointer not in allocated block") gothrow("runtime.SetFinalizer: pointer not in allocated block")
......
...@@ -51,10 +51,26 @@ func clearpools() { ...@@ -51,10 +51,26 @@ func clearpools() {
if c := p.mcache; c != nil { if c := p.mcache; c != nil {
c.tiny = nil c.tiny = nil
c.tinysize = 0 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 c.sudogcache = nil
} }
// clear defer pools // clear defer pools
for i := range p.deferpool { 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 p.deferpool[i] = nil
} }
} }
......
...@@ -165,6 +165,7 @@ func acquireSudog() *sudog { ...@@ -165,6 +165,7 @@ func acquireSudog() *sudog {
gothrow("acquireSudog: found s.elem != nil in cache") gothrow("acquireSudog: found s.elem != nil in cache")
} }
c.sudogcache = s.next c.sudogcache = s.next
s.next = nil
return s return s
} }
...@@ -190,6 +191,15 @@ func releaseSudog(s *sudog) { ...@@ -190,6 +191,15 @@ func releaseSudog(s *sudog) {
if s.selectdone != nil { if s.selectdone != nil {
gothrow("runtime: sudog with non-nil selectdone") 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() gp := getg()
if gp.param != nil { if gp.param != nil {
gothrow("runtime: releaseSudog with non-nil gp.param") 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 ...@@ -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_atomic32_compare_exchange
//go:cgo_import_static __tsan_go_atomic64_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 // start/end of heap for race_amd64.s
var racearenastart uintptr var racearenastart uintptr
var racearenaend uintptr var racearenaend uintptr
...@@ -99,7 +103,7 @@ func racecall(*byte, uintptr, uintptr, uintptr, uintptr) ...@@ -99,7 +103,7 @@ func racecall(*byte, uintptr, uintptr, uintptr, uintptr)
//go:nosplit //go:nosplit
func isvalidaddr(addr unsafe.Pointer) bool { func isvalidaddr(addr unsafe.Pointer) bool {
return racearenastart <= uintptr(addr) && uintptr(addr) < racearenaend || 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 //go:nosplit
...@@ -113,9 +117,36 @@ func raceinit() uintptr { ...@@ -113,9 +117,36 @@ func raceinit() uintptr {
racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0) racecall(&__tsan_init, uintptr(unsafe.Pointer(&racectx)), funcPC(racesymbolizethunk), 0, 0)
// Round data segment to page boundaries, because it's used in mmap(). // Round data segment to page boundaries, because it's used in mmap().
start := uintptr(unsafe.Pointer(&noptrdata)) &^ (_PageSize - 1) start := ^uintptr(0)
size := round(uintptr(unsafe.Pointer(&enoptrbss))-start, _PageSize) 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) racecall(&__tsan_map_shadow, start, size, 0, 0)
racedatastart = start
racedataend = start + size
return racectx return racectx
} }
......
...@@ -139,17 +139,15 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0 ...@@ -139,17 +139,15 @@ TEXT racecalladdr<>(SB), NOSPLIT, $0-0
get_tls(R12) get_tls(R12)
MOVQ g(R12), R14 MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context 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) CMPQ RARG1, runtime·racearenastart(SB)
JB data JB data
CMPQ RARG1, runtime·racearenaend(SB) CMPQ RARG1, runtime·racearenaend(SB)
JB call JB call
data: data:
MOVQ $runtime·noptrdata(SB), R13 CMPQ RARG1, runtime·racedatastart(SB)
CMPQ RARG1, R13
JB ret JB ret
MOVQ $runtime·enoptrbss(SB), R13 CMPQ RARG1, runtime·racedataend(SB)
CMPQ RARG1, R13
JAE ret JAE ret
call: call:
MOVQ AX, AX // w/o this 6a miscompiles this function MOVQ AX, AX // w/o this 6a miscompiles this function
...@@ -167,6 +165,7 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8 ...@@ -167,6 +165,7 @@ TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8
MOVQ callpc+0(FP), RARG1 MOVQ callpc+0(FP), RARG1
// void __tsan_func_enter(ThreadState *thr, void *pc); // void __tsan_func_enter(ThreadState *thr, void *pc);
MOVQ $__tsan_func_enter(SB), AX MOVQ $__tsan_func_enter(SB), AX
// racecall<> preserves R15
CALL racecall<>(SB) CALL racecall<>(SB)
MOVQ R15, DX // restore function entry context MOVQ R15, DX // restore function entry context
RET RET
...@@ -307,13 +306,45 @@ TEXT sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0 ...@@ -307,13 +306,45 @@ TEXT sync∕atomic·CompareAndSwapPointer(SB), NOSPLIT, $0-0
TEXT racecallatomic<>(SB), NOSPLIT, $0-0 TEXT racecallatomic<>(SB), NOSPLIT, $0-0
// Trigger SIGSEGV early. // Trigger SIGSEGV early.
MOVQ 16(SP), R12 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) get_tls(R12)
MOVQ g(R12), R14 MOVQ g(R12), R14
MOVQ g_racectx(R14), RARG0 // goroutine context MOVQ g_racectx(R14), RARG0 // goroutine context
MOVQ 8(SP), RARG1 // caller pc MOVQ 8(SP), RARG1 // caller pc
MOVQ (SP), RARG2 // pc MOVQ (SP), RARG2 // pc
LEAQ 16(SP), RARG3 // arguments 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) JMP racecall<>(SB)
// void runtime·racecall(void(*f)(...), ...) // void runtime·racecall(void(*f)(...), ...)
......
...@@ -404,6 +404,7 @@ loop: ...@@ -404,6 +404,7 @@ loop:
} }
} }
sgnext = sglist.waitlink sgnext = sglist.waitlink
sglist.waitlink = nil
releaseSudog(sglist) releaseSudog(sglist)
sglist = sgnext sglist = sgnext
} }
...@@ -641,6 +642,7 @@ func (q *waitq) dequeueSudoG(s *sudog) { ...@@ -641,6 +642,7 @@ func (q *waitq) dequeueSudoG(s *sudog) {
if q.last == sgp { if q.last == sgp {
q.last = prevsgp q.last = prevsgp
} }
s.next = nil
return return
} }
l = &sgp.next l = &sgp.next
......
...@@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) { ...@@ -201,6 +201,7 @@ func syncsemacquire(s *syncSema) {
} }
unlock(&s.lock) unlock(&s.lock)
if wake != nil { if wake != nil {
wake.next = nil
goready(wake.g) goready(wake.g)
} }
} else { } else {
...@@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) { ...@@ -242,6 +243,7 @@ func syncsemrelease(s *syncSema, n uint32) {
if wake.releasetime != 0 { if wake.releasetime != 0 {
wake.releasetime = cputicks() wake.releasetime = cputicks()
} }
wake.next = nil
goready(wake.g) goready(wake.g)
n-- n--
} }
......
...@@ -154,7 +154,7 @@ func setcallerpc(argp unsafe.Pointer, pc uintptr) ...@@ -154,7 +154,7 @@ func setcallerpc(argp unsafe.Pointer, pc uintptr)
// //
// func f(arg1, arg2, arg3 int) { // func f(arg1, arg2, arg3 int) {
// pc := getcallerpc(unsafe.Pointer(&arg1)) // 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 // These two lines find the PC and SP immediately following
......
...@@ -19,8 +19,6 @@ type SysProcAttr struct { ...@@ -19,8 +19,6 @@ type SysProcAttr struct {
Setpgid bool // Set process group ID to new pid (SYSV setpgrp) Setpgid bool // Set process group ID to new pid (SYSV setpgrp)
Setctty bool // Set controlling terminal to fd 0 Setctty bool // Set controlling terminal to fd 0
Noctty bool // Detach fd 0 from controlling terminal 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. // Implemented in runtime package.
...@@ -81,22 +79,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr ...@@ -81,22 +79,7 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
if r1 != 0 { if r1 != 0 {
// parent; return PID // parent; return PID
runtime_AfterFork() runtime_AfterFork()
pid = int(r1) return int(r1), 0
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
} }
// Fork succeeded, now in child. // Fork succeeded, now in child.
...@@ -118,30 +101,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr ...@@ -118,30 +101,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
} }
// Set process group // Set process group
if sys.Joinpgrp != 0 { if sys.Setpgid {
// 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.
_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0) _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
if err1 != 0 { if err1 != 0 {
goto childerror 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 // Chroot
......
...@@ -29,8 +29,6 @@ type SysProcAttr struct { ...@@ -29,8 +29,6 @@ type SysProcAttr struct {
Ctty int // Controlling TTY fd (Linux only) Ctty int // Controlling TTY fd (Linux only)
Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only) Pdeathsig Signal // Signal that the process will get when its parent dies (Linux only)
Cloneflags uintptr // Flags for clone calls (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. UidMappings []SysProcIDMap // User ID mappings for user namespaces.
GidMappings []SysProcIDMap // Group 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 ...@@ -105,19 +103,6 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
Close(p[1]) 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 return pid, 0
} }
...@@ -179,30 +164,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr ...@@ -179,30 +164,11 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr
} }
// Set process group // Set process group
if sys.Joinpgrp != 0 { if sys.Setpgid {
// 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.
_, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0) _, _, err1 = RawSyscall(SYS_SETPGID, 0, 0, 0)
if err1 != 0 { if err1 != 0 {
goto childerror 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 // 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