]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.cc] all: merge default (e4ab8f908aac) into dev.cc
authorRuss Cox <rsc@golang.org>
Thu, 20 Nov 2014 16:48:08 +0000 (11:48 -0500)
committerRuss Cox <rsc@golang.org>
Thu, 20 Nov 2014 16:48:08 +0000 (11:48 -0500)
TBR=austin
CC=golang-codereviews
https://golang.org/cl/179040044

45 files changed:
.hgtags
AUTHORS
CONTRIBUTORS
doc/go1.4.html
doc/go_spec.html
doc/gopher/fiveyears.jpg [new file with mode: 0644]
doc/install.html
misc/makerelease/makerelease.go
src/cmd/5g/reg.c
src/cmd/cgo/doc.go
src/cmd/internal/goobj/read.go [moved from src/debug/goobj/read.go with 100% similarity]
src/cmd/internal/goobj/read_test.go [moved from src/debug/goobj/read_test.go with 100% similarity]
src/cmd/internal/objfile/goobj.go
src/cmd/link/auto.go
src/cmd/link/auto_test.go
src/cmd/link/dead.go
src/cmd/link/dead_test.go
src/cmd/link/layout.go
src/cmd/link/link_test.go
src/cmd/link/pclntab.go
src/cmd/link/pclntab_test.go
src/cmd/link/prog.go
src/cmd/link/runtime.go
src/cmd/link/scan.go
src/cmd/pprof/internal/report/source.go
src/crypto/x509/root_unix.go
src/hash/crc32/crc32.go
src/net/http/fs.go
src/net/url/example_test.go
src/regexp/syntax/regexp.go
src/run.bash
src/runtime/chan.go
src/runtime/heapdump.go
src/runtime/malloc.go
src/runtime/mgc0.go
src/runtime/proc.go
src/runtime/race/race_unix_test.go [new file with mode: 0644]
src/runtime/race1.go
src/runtime/race_amd64.s
src/runtime/select.go
src/runtime/sema.go
src/runtime/stubs.go
src/syscall/exec_bsd.go
src/syscall/exec_linux.go
test/fixedbugs/issue9110.go [new file with mode: 0644]

diff --git a/.hgtags b/.hgtags
index edd2163f701248fa6ce3debb20409531c8bc0c53..9867bc339f9a316448888652756f371270d66d97 100644 (file)
--- a/.hgtags
+++ b/.hgtags
@@ -136,3 +136,4 @@ f8b50ad4cac4d4c4ecf48324b4f512f65e82cc1c go1.3beta1
 f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 go1.3.3
 f44017549ff9c3cc5eef74ebe7276cd0dfc066b6 release
 1fdfd7dfaedb1b7702141617e621ab7328a236a1 go1.4beta1
+bffdd0cae380ce1ccf3e98ed6b6cd53fece7ba72 go1.4rc1
diff --git a/AUTHORS b/AUTHORS
index 48a262bbd7c52a257d778273994d83cfb02d6a37..46fd9fd2951798f2a1a5c8b8ca81f1bf83a03f47 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -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>
index ec69858b605ede830e06ec7a81670181c021b0f2..b5e709ed6e6faf557f456ab2a282f7c5127c0780 100644 (file)
@@ -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>
index ac63ade60adc2f9834e973a91cde4eb42c110cc7..883352e34fe4b1e8d579bcbc568a46c6a8720e3f 100644 (file)
@@ -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>
index 050c06465de602daf2f79e28a2cc2abf181fae1d..ca0deb56a3ebd24c442a4dbb3ed5c207673ad220 100644 (file)
@@ -1,6 +1,6 @@
 <!--{
        "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>
 
 
diff --git a/doc/gopher/fiveyears.jpg b/doc/gopher/fiveyears.jpg
new file mode 100644 (file)
index 0000000..df10648
Binary files /dev/null and b/doc/gopher/fiveyears.jpg differ
index d6984c2447b3df6708cd96d8d593234f2a6bd8a4..9561fdde21063c4e7b1995fa53171c74cc929960 100644 (file)
@@ -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>
index e94efdbceeed48e327cef832f875859dce5cab75..8cf6be2a434d35eb2b3d0b6624ce554006e90627 100644 (file)
@@ -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.
index 56ea7826e2deefcd01c565a1bb7cc022a6ae19a0..611310f124f75134dafddd93c7df0e245498deff 100644 (file)
@@ -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;
index 69c7ce893c3d1516c8fba1316f3c128c9bbd988a..6179c7afd19eb1d587c5bedce46d5b375c64834b 100644 (file)
@@ -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:
index a1d773023dc551bbfd4103b3b186e3b128306d34..6b1607a1725a5b598bb0f1fcbac2cb77080db9c0 100644 (file)
@@ -7,7 +7,7 @@
 package objfile
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "fmt"
        "os"
 )
index f9228e8cab179d0e1771e691f0afb42c0f89d8a9..21f6d6082722d923beb93b47a797e246ebcb8908 100644 (file)
@@ -10,7 +10,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "strconv"
        "strings"
 )
index 27f8e2b96d63b38ff430158b7c8168dd0b07a58c..f99e097a9c382f3d936beadd05b41855e86437ab 100644 (file)
@@ -13,7 +13,7 @@ package main
 
 import (
        "bytes"
-       "debug/goobj"
+       "cmd/internal/goobj"
        "testing"
 )
 
index e1e775eb3be4ebd28e462e884170d4c2e42ad4ce..ee23a61f81f96c097fc367e3e4e603bf6b848611 100644 (file)
@@ -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
index 2e179b453b1d5a8af8accd6813f66f07141e5b69..eb34d0580d1889e486ee29c220d01b4f7c1b5c2b 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "reflect"
        "strings"
        "testing"
index 149ebced0fd2e931ae1aa4eb56eeb52196234a3d..d5c291e255370ff36ed1bb8eb45fa6e09545ecc0 100644 (file)
@@ -7,7 +7,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
 )
 
 // A layoutSection describes a single section to add to the
index 984796784e7c40cb017012c22e00061fe4964066..b5ae15fc7108a008fd44096895ef3e7e053eef2c 100644 (file)
@@ -6,7 +6,7 @@ package main
 
 import (
        "bytes"
-       "debug/goobj"
+       "cmd/internal/goobj"
        "io/ioutil"
        "testing"
 )
index 232d586bf28ec1529ac8f55f331b76df28a7248c..2d131781f2badbc4a045548432290589d023c064 100644 (file)
@@ -7,7 +7,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "encoding/binary"
        "os"
        "sort"
index 19953f5797b238e93a4a07a9cd9a0a1a657650bd..ea808067427e0b98e65b97d354d5768c8e170d77 100644 (file)
@@ -6,7 +6,7 @@ package main
 
 import (
        "bytes"
-       "debug/goobj"
+       "cmd/internal/goobj"
        "fmt"
        "math/rand"
        "sort"
index a52b5ff9b214d2a5a44bd4963e0c9665fe3a7ac0..77fb1ece5b1685c09358973870dadf7001830621 100644 (file)
@@ -5,7 +5,7 @@
 package main
 
 import (
-       "debug/goobj"
+       "cmd/internal/goobj"
        "encoding/binary"
        "fmt"
        "go/build"
index b0c1ac98a68eeca2b1185f2be7b6b203d5568b46..acda2d24d6c6cc0c5ecbc8dc0099ce2b0057b315 100644 (file)
@@ -7,7 +7,7 @@
 
 package main
 
-import "debug/goobj"
+import "cmd/internal/goobj"
 
 func (p *Prog) runtime() {
        p.pclntab()
index 0720e039b83c1df6c668cf969e930e8232c0194e..7feb0d89002abf0b25c522fb79bf35032079f19d 100644 (file)
@@ -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
index 57300dd91a8d4e9a179a0f856c29c0aa08b2b8b7..73ae1b4ea2efadf747beab8629dff90cd7a72acc 100644 (file)
@@ -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])
index c65f626ac8bfb6fd2111735b7645abf82614ea77..f77d6c0c57f79e386349801cb57ed2baa88e3c3c 100644 (file)
@@ -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
index a2a21a06f950bf722f78adf70a46867b2c0d9042..6a6b9473bea45b9db127a5c03eb0809f061e9147 100644 (file)
@@ -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.
index 7bd777b712da9ff5961ea28dacd9f1c204ea28b7..e322f710a5d95361e9e6c0055641137b1b05b65d 100644 (file)
@@ -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
index 56c5dc696a20e747c140c62a0536c65023d18397..e55c1aa166ea5ceab78004c87cae3fdb0f4f9816 100644 (file)
@@ -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
+       //
+}
index 329a90e01294076d07f12086237d8b8669234fd7..cea7d9e04fec70ac66435c0aae94398b07a57ba2 100644 (file)
@@ -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
index d9b985fd15350e3ad49077cea6199442a31ccf4e..6b9ecc33c299c3f7ebfd386c412beb3ab8c7e63a 100755 (executable)
@@ -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.
index bb0110f94cf1b5a5c6939b9d860e7455a8477bdb..330422ad0908d6ab5391e8dd0e8e83ca4a94539b 100644 (file)
@@ -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
                }
index c942e01639953256a8b3ceb62e2d3c695230113d..0c1a60c8bb85608c7295c54b40a162f5de5a5c49 100644 (file)
@@ -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
 
index 20cb6818d23cb380da9188eec3ba6757aa185857..d73d1ba6a613865bed394273f401071d26836bd8 100644 (file)
@@ -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")
index 6d4ae61c112fa53d9c0685c6e401128e7f09a3a8..38406f33a873839a5a03edd32bd60070fce5d7ba 100644 (file)
@@ -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
                }
        }
index 05ecb3d9eb9abae78dd53b4e4e6dfb4a7c2a2f4d..50920afe8bf68da83f5aaa67103615dc6138d5a1 100644 (file)
@@ -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")
diff --git a/src/runtime/race/race_unix_test.go b/src/runtime/race/race_unix_test.go
new file mode 100644 (file)
index 0000000..84f0ace
--- /dev/null
@@ -0,0 +1,30 @@
+// 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)
+}
index 4c580429c8690dd478783f8a837617b5259cdf09..2ec2bee65b6e9fc9d8042765b67c92e09d93383a 100644 (file)
@@ -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
 }
index a7f44870a8671e908efe3d6497ad7b5639a5ad86..d54d9798f032ccc6c2f8043e3ab9c6d87f008a07 100644 (file)
@@ -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)(...), ...)
index fe9178763e02d3f13334b6678461f8198085837c..6717b93956b33a58a87485ac9b9ae058427a71b8 100644 (file)
@@ -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
index d2a028c01b1fe9f5e5332dd915fa11a201db7f11..26dbd30ea3f9375f1d2ca843014556f267d857a2 100644 (file)
@@ -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--
        }
index 217307a1ed0a65260a4cdcb87d760ae522291ed2..aa7577cf9438f27abcb0403516230f63c8140baf 100644 (file)
@@ -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
index 7c2c1f7071a8094a43ff89ccb73a42ea103849ef..ff78f197f1fb30af337e1618264f56aa701a1302 100644 (file)
@@ -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
index 72e2f0b69c82f64bf191515d6af4d5bc9d8949b6..042c20a46812feb1d88e0f928e7e61382480e64a 100644 (file)
@@ -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
diff --git a/test/fixedbugs/issue9110.go b/test/fixedbugs/issue9110.go
new file mode 100644 (file)
index 0000000..7294633
--- /dev/null
@@ -0,0 +1,90 @@
+// 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")
+       }
+}