summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2019-04-08 18:36:25 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2019-04-08 18:36:25 +0000
commit04862afe9f5c54a420823f95bb6ae152eec64b8b (patch)
tree7b77ac8c94329f12ebde6ac6c869b0af05a92f85
parent8108dfde82ad6ec43613107b2c156999e6a5cbe7 (diff)
libgo: update to Go 1.12.2
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/170706 From-SVN: r270214
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--libgo/MERGE2
-rw-r--r--libgo/VERSION2
-rw-r--r--libgo/go/cmd/go/internal/load/pkg.go53
-rw-r--r--libgo/go/cmd/go/internal/load/test.go23
-rw-r--r--libgo/go/cmd/go/internal/test/test.go2
-rw-r--r--libgo/go/cmd/go/internal/work/build.go5
-rw-r--r--libgo/go/cmd/go/internal/work/exec.go1
-rw-r--r--libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt6
-rw-r--r--libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt43
-rw-r--r--libgo/go/internal/poll/fd_windows.go6
-rw-r--r--libgo/go/net/http/httputil/reverseproxy.go5
-rw-r--r--libgo/go/net/http/httputil/reverseproxy_test.go42
-rw-r--r--libgo/go/net/lookup.go5
-rw-r--r--libgo/go/net/lookup_test.go89
-rw-r--r--libgo/go/os/path.go1
-rw-r--r--libgo/go/os/path_unix.go2
-rw-r--r--libgo/go/os/removeall_at.go38
-rw-r--r--libgo/go/os/removeall_test.go15
-rw-r--r--libgo/go/runtime/runtime-lldb_test.go1
-rw-r--r--libgo/go/syscall/security_windows.go1
21 files changed, 270 insertions, 74 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 64844411c8c..1e4da036b8f 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-392e9b3da473070f24dbe6c12c282a0e06e73b54
+a69f7c05f1880bb90544fb0c3577109cb1d7f3ab
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/libgo/MERGE b/libgo/MERGE
index d456361af0b..37b7480a671 100644
--- a/libgo/MERGE
+++ b/libgo/MERGE
@@ -1,4 +1,4 @@
-0380c9ad38843d523d9c9804fe300cb7edd7cd3c
+ac02fdec7cd16ea8d3de1fc33def9cfabec5170d
The first line of this file holds the git revision number of the
last merge done from the master library sources.
diff --git a/libgo/VERSION b/libgo/VERSION
index f325447817b..b9c64397147 100644
--- a/libgo/VERSION
+++ b/libgo/VERSION
@@ -1 +1 @@
-go1.12.1
+go1.12.2
diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go
index 543250e86c1..5e511dbdbd3 100644
--- a/libgo/go/cmd/go/internal/load/pkg.go
+++ b/libgo/go/cmd/go/internal/load/pkg.go
@@ -1184,6 +1184,36 @@ var cgoSyscallExclude = map[string]bool{
var foldPath = make(map[string]string)
+// DefaultExecName returns the default executable name
+// for a package with the import path importPath.
+//
+// The default executable name is the last element of the import path.
+// In module-aware mode, an additional rule is used. If the last element
+// is a vN path element specifying the major version, then the second last
+// element of the import path is used instead.
+func DefaultExecName(importPath string) string {
+ _, elem := pathpkg.Split(importPath)
+ if cfg.ModulesEnabled {
+ // If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
+ // See golang.org/issue/24667.
+ isVersion := func(v string) bool {
+ if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
+ return false
+ }
+ for i := 2; i < len(v); i++ {
+ if c := v[i]; c < '0' || '9' < c {
+ return false
+ }
+ }
+ return true
+ }
+ if isVersion(elem) {
+ _, elem = pathpkg.Split(pathpkg.Dir(importPath))
+ }
+ }
+ return elem
+}
+
// load populates p using information from bp, err, which should
// be the result of calling build.Context.Import.
func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
@@ -1226,7 +1256,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
}
_, elem := filepath.Split(p.Dir)
if cfg.ModulesEnabled {
- // NOTE(rsc): Using p.ImportPath instead of p.Dir
+ // NOTE(rsc,dmitshur): Using p.ImportPath instead of p.Dir
// makes sure we install a package in the root of a
// cached module directory as that package name
// not name@v1.2.3.
@@ -1235,26 +1265,9 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
// even for non-module-enabled code,
// but I'm not brave enough to change the
// non-module behavior this late in the
- // release cycle. Maybe for Go 1.12.
+ // release cycle. Can be done for Go 1.13.
// See golang.org/issue/26869.
- _, elem = pathpkg.Split(p.ImportPath)
-
- // If this is example.com/mycmd/v2, it's more useful to install it as mycmd than as v2.
- // See golang.org/issue/24667.
- isVersion := func(v string) bool {
- if len(v) < 2 || v[0] != 'v' || v[1] < '1' || '9' < v[1] {
- return false
- }
- for i := 2; i < len(v); i++ {
- if c := v[i]; c < '0' || '9' < c {
- return false
- }
- }
- return true
- }
- if isVersion(elem) {
- _, elem = pathpkg.Split(pathpkg.Dir(p.ImportPath))
- }
+ elem = DefaultExecName(p.ImportPath)
}
full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
if cfg.BuildContext.GOOS != base.ToolGOOS || cfg.BuildContext.GOARCH != base.ToolGOARCH {
diff --git a/libgo/go/cmd/go/internal/load/test.go b/libgo/go/cmd/go/internal/load/test.go
index c0e06676df1..7385c4e5030 100644
--- a/libgo/go/cmd/go/internal/load/test.go
+++ b/libgo/go/cmd/go/internal/load/test.go
@@ -268,17 +268,8 @@ func GetTestPackagesFor(p *Package, cover *TestCover) (pmain, ptest, pxtest *Pac
pmain.Imports = pmain.Imports[:w]
pmain.Internal.RawImports = str.StringList(pmain.Imports)
- if ptest != p {
- // We have made modifications to the package p being tested
- // and are rebuilding p (as ptest).
- // Arrange to rebuild all packages q such that
- // the test depends on q and q depends on p.
- // This makes sure that q sees the modifications to p.
- // Strictly speaking, the rebuild is only necessary if the
- // modifications to p change its export metadata, but
- // determining that is a bit tricky, so we rebuild always.
- recompileForTest(pmain, p, ptest, pxtest)
- }
+ // Replace pmain's transitive dependencies with test copies, as necessary.
+ recompileForTest(pmain, p, ptest, pxtest)
// Should we apply coverage analysis locally,
// only for this package and only for this test?
@@ -325,6 +316,14 @@ Search:
return stk
}
+// recompileForTest copies and replaces certain packages in pmain's dependency
+// graph. This is necessary for two reasons. First, if ptest is different than
+// preal, packages that import the package under test should get ptest instead
+// of preal. This is particularly important if pxtest depends on functionality
+// exposed in test sources in ptest. Second, if there is a main package
+// (other than pmain) anywhere, we need to clear p.Internal.BuildInfo in
+// the test copy to prevent link conflicts. This may happen if both -coverpkg
+// and the command line patterns include multiple main packages.
func recompileForTest(pmain, preal, ptest, pxtest *Package) {
// The "test copy" of preal is ptest.
// For each package that depends on preal, make a "test copy"
@@ -367,7 +366,7 @@ func recompileForTest(pmain, preal, ptest, pxtest *Package) {
// Don't compile build info from a main package. This can happen
// if -coverpkg patterns include main packages, since those packages
- // are imported by pmain.
+ // are imported by pmain. See golang.org/issue/30907.
if p.Internal.BuildInfo != "" && p != pmain {
split()
}
diff --git a/libgo/go/cmd/go/internal/test/test.go b/libgo/go/cmd/go/internal/test/test.go
index 332f3124415..b72eace55ab 100644
--- a/libgo/go/cmd/go/internal/test/test.go
+++ b/libgo/go/cmd/go/internal/test/test.go
@@ -805,7 +805,7 @@ func builderTest(b *work.Builder, p *load.Package) (buildAction, runAction, prin
if p.ImportPath == "command-line-arguments" {
elem = p.Name
} else {
- _, elem = path.Split(p.ImportPath)
+ elem = load.DefaultExecName(p.ImportPath)
}
testBinary := elem + ".test"
diff --git a/libgo/go/cmd/go/internal/work/build.go b/libgo/go/cmd/go/internal/work/build.go
index 145b87513a9..ed66df22c33 100644
--- a/libgo/go/cmd/go/internal/work/build.go
+++ b/libgo/go/cmd/go/internal/work/build.go
@@ -10,7 +10,6 @@ import (
"go/build"
"os"
"os/exec"
- "path"
"path/filepath"
"runtime"
"strings"
@@ -285,7 +284,7 @@ func runBuild(cmd *base.Command, args []string) {
pkgs := load.PackagesForBuild(args)
if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
- _, cfg.BuildO = path.Split(pkgs[0].ImportPath)
+ cfg.BuildO = load.DefaultExecName(pkgs[0].ImportPath)
cfg.BuildO += cfg.ExeSuffix
}
@@ -518,7 +517,7 @@ func InstallPackages(patterns []string, pkgs []*load.Package) {
if len(patterns) == 0 && len(pkgs) == 1 && pkgs[0].Name == "main" {
// Compute file 'go build' would have created.
// If it exists and is an executable file, remove it.
- _, targ := filepath.Split(pkgs[0].ImportPath)
+ targ := load.DefaultExecName(pkgs[0].ImportPath)
targ += cfg.ExeSuffix
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
fi, err := os.Stat(targ)
diff --git a/libgo/go/cmd/go/internal/work/exec.go b/libgo/go/cmd/go/internal/work/exec.go
index fc052b3e45a..53027246614 100644
--- a/libgo/go/cmd/go/internal/work/exec.go
+++ b/libgo/go/cmd/go/internal/work/exec.go
@@ -214,6 +214,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
if p.Internal.CoverMode != "" {
fmt.Fprintf(h, "cover %q %q\n", p.Internal.CoverMode, b.toolID("cover"))
}
+ fmt.Fprintf(h, "modinfo %q\n", p.Internal.BuildInfo)
// Configuration specific to compiler toolchain.
switch cfg.BuildToolchainName {
diff --git a/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt b/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt
index cfa91f08a5d..3acd6379311 100644
--- a/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt
+++ b/libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt
@@ -13,3 +13,9 @@ import "rsc.io/quote"
func main() {
println(quote.Hello())
}
+-- fortune_test.go --
+package main
+
+import "testing"
+
+func TestFortuneV2(t *testing.T) {}
diff --git a/libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt b/libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
new file mode 100644
index 00000000000..ab7cd66949d
--- /dev/null
+++ b/libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
@@ -0,0 +1,43 @@
+# This test checks that multiple main packages can be tested
+# with -coverpkg=all without duplicate symbol errors.
+# Verifies golang.org/issue/30374.
+
+env GO111MODULE=on
+
+[short] skip
+
+go test -coverpkg=all ./...
+
+-- go.mod --
+module example.com/cov
+
+-- mainonly/mainonly.go --
+package main
+
+func main() {}
+
+-- mainwithtest/mainwithtest.go --
+package main
+
+func main() {}
+
+func Foo() {}
+
+-- mainwithtest/mainwithtest_test.go --
+package main
+
+import "testing"
+
+func TestFoo(t *testing.T) {
+ Foo()
+}
+
+-- xtest/x.go --
+package x
+
+-- xtest/x_test.go --
+package x_test
+
+import "testing"
+
+func TestX(t *testing.T) {}
diff --git a/libgo/go/internal/poll/fd_windows.go b/libgo/go/internal/poll/fd_windows.go
index 19d9a12dad8..f860b82c974 100644
--- a/libgo/go/internal/poll/fd_windows.go
+++ b/libgo/go/internal/poll/fd_windows.go
@@ -660,6 +660,10 @@ func (fd *FD) Write(buf []byte) (int, error) {
return 0, err
}
defer fd.writeUnlock()
+ if fd.isFile || fd.isDir || fd.isConsole {
+ fd.l.Lock()
+ defer fd.l.Unlock()
+ }
ntotal := 0
for len(buf) > 0 {
@@ -670,8 +674,6 @@ func (fd *FD) Write(buf []byte) (int, error) {
var n int
var err error
if fd.isFile || fd.isDir || fd.isConsole {
- fd.l.Lock()
- defer fd.l.Unlock()
if fd.isConsole {
n, err = fd.writeConsole(b)
} else {
diff --git a/libgo/go/net/http/httputil/reverseproxy.go b/libgo/go/net/http/httputil/reverseproxy.go
index 4e10bf39971..4b165d65a6a 100644
--- a/libgo/go/net/http/httputil/reverseproxy.go
+++ b/libgo/go/net/http/httputil/reverseproxy.go
@@ -389,6 +389,11 @@ func (p *ReverseProxy) copyResponse(dst io.Writer, src io.Reader, flushInterval
latency: flushInterval,
}
defer mlw.stop()
+
+ // set up initial timer so headers get flushed even if body writes are delayed
+ mlw.flushPending = true
+ mlw.t = time.AfterFunc(flushInterval, mlw.delayedFlush)
+
dst = mlw
}
}
diff --git a/libgo/go/net/http/httputil/reverseproxy_test.go b/libgo/go/net/http/httputil/reverseproxy_test.go
index 5edefa08e55..367ba73ae24 100644
--- a/libgo/go/net/http/httputil/reverseproxy_test.go
+++ b/libgo/go/net/http/httputil/reverseproxy_test.go
@@ -9,6 +9,7 @@ package httputil
import (
"bufio"
"bytes"
+ "context"
"errors"
"fmt"
"io"
@@ -317,6 +318,47 @@ func TestReverseProxyFlushInterval(t *testing.T) {
}
}
+func TestReverseProxyFlushIntervalHeaders(t *testing.T) {
+ const expected = "hi"
+ stopCh := make(chan struct{})
+ backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("MyHeader", expected)
+ w.WriteHeader(200)
+ w.(http.Flusher).Flush()
+ <-stopCh
+ }))
+ defer backend.Close()
+ defer close(stopCh)
+
+ backendURL, err := url.Parse(backend.URL)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ proxyHandler := NewSingleHostReverseProxy(backendURL)
+ proxyHandler.FlushInterval = time.Microsecond
+
+ frontend := httptest.NewServer(proxyHandler)
+ defer frontend.Close()
+
+ req, _ := http.NewRequest("GET", frontend.URL, nil)
+ req.Close = true
+
+ ctx, cancel := context.WithTimeout(req.Context(), 10*time.Second)
+ defer cancel()
+ req = req.WithContext(ctx)
+
+ res, err := frontend.Client().Do(req)
+ if err != nil {
+ t.Fatalf("Get: %v", err)
+ }
+ defer res.Body.Close()
+
+ if res.Header.Get("MyHeader") != expected {
+ t.Errorf("got header %q; expected %q", res.Header.Get("MyHeader"), expected)
+ }
+}
+
func TestReverseProxyCancelation(t *testing.T) {
const backendResponse = "I am the backend"
diff --git a/libgo/go/net/lookup.go b/libgo/go/net/lookup.go
index e10889331e4..08e8d013855 100644
--- a/libgo/go/net/lookup.go
+++ b/libgo/go/net/lookup.go
@@ -262,8 +262,9 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IP
// only the values in context. See Issue 28600.
lookupGroupCtx, lookupGroupCancel := context.WithCancel(withUnexpiredValuesPreserved(ctx))
+ lookupKey := network + "\000" + host
dnsWaitGroup.Add(1)
- ch, called := r.getLookupGroup().DoChan(host, func() (interface{}, error) {
+ ch, called := r.getLookupGroup().DoChan(lookupKey, func() (interface{}, error) {
defer dnsWaitGroup.Done()
return testHookLookupIP(lookupGroupCtx, resolverFunc, network, host)
})
@@ -280,7 +281,7 @@ func (r *Resolver) lookupIPAddr(ctx context.Context, network, host string) ([]IP
// let the lookup continue uncanceled, and let later
// lookups with the same key share the result.
// See issues 8602, 20703, 22724.
- if r.getLookupGroup().ForgetUnshared(host) {
+ if r.getLookupGroup().ForgetUnshared(lookupKey) {
lookupGroupCancel()
} else {
go func() {
diff --git a/libgo/go/net/lookup_test.go b/libgo/go/net/lookup_test.go
index 85bcb2b8960..28a895e15d1 100644
--- a/libgo/go/net/lookup_test.go
+++ b/libgo/go/net/lookup_test.go
@@ -16,6 +16,7 @@ import (
"sort"
"strings"
"sync"
+ "sync/atomic"
"testing"
"time"
)
@@ -253,14 +254,11 @@ func TestLookupGmailTXT(t *testing.T) {
}
}
-var lookupGooglePublicDNSAddrTests = []struct {
- addr, name string
-}{
- {"8.8.8.8", ".google.com."},
- {"8.8.4.4", ".google.com."},
-
- {"2001:4860:4860::8888", ".google.com."},
- {"2001:4860:4860::8844", ".google.com."},
+var lookupGooglePublicDNSAddrTests = []string{
+ "8.8.8.8",
+ "8.8.4.4",
+ "2001:4860:4860::8888",
+ "2001:4860:4860::8844",
}
func TestLookupGooglePublicDNSAddr(t *testing.T) {
@@ -272,8 +270,8 @@ func TestLookupGooglePublicDNSAddr(t *testing.T) {
defer dnsWaitGroup.Wait()
- for _, tt := range lookupGooglePublicDNSAddrTests {
- names, err := LookupAddr(tt.addr)
+ for _, ip := range lookupGooglePublicDNSAddrTests {
+ names, err := LookupAddr(ip)
if err != nil {
t.Fatal(err)
}
@@ -281,8 +279,8 @@ func TestLookupGooglePublicDNSAddr(t *testing.T) {
t.Error("got no record")
}
for _, name := range names {
- if !strings.HasSuffix(name, tt.name) {
- t.Errorf("got %s; want a record containing %s", name, tt.name)
+ if !strings.HasSuffix(name, ".google.com.") && !strings.HasSuffix(name, ".google.") {
+ t.Errorf("got %q; want a record ending in .google.com. or .google.", name)
}
}
}
@@ -658,8 +656,8 @@ func testDots(t *testing.T, mode string) {
t.Errorf("LookupAddr(8.8.8.8): %v (mode=%v)", err, mode)
} else {
for _, name := range names {
- if !strings.HasSuffix(name, ".google.com.") {
- t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com. with trailing dot (mode=%v)", names, mode)
+ if !strings.HasSuffix(name, ".google.com.") && !strings.HasSuffix(name, ".google.") {
+ t.Errorf("LookupAddr(8.8.8.8) = %v, want names ending in .google.com or .google with trailing dot (mode=%v)", names, mode)
break
}
}
@@ -1096,6 +1094,69 @@ func TestLookupIPAddrPreservesContextValues(t *testing.T) {
}
}
+// Issue 30521: The lookup group should call the resolver for each network.
+func TestLookupIPAddrConcurrentCallsForNetworks(t *testing.T) {
+ origTestHookLookupIP := testHookLookupIP
+ defer func() { testHookLookupIP = origTestHookLookupIP }()
+
+ queries := [][]string{
+ {"udp", "golang.org"},
+ {"udp4", "golang.org"},
+ {"udp6", "golang.org"},
+ {"udp", "golang.org"},
+ {"udp", "golang.org"},
+ }
+ results := map[[2]string][]IPAddr{
+ {"udp", "golang.org"}: {
+ {IP: IPv4(127, 0, 0, 1)},
+ {IP: IPv6loopback},
+ },
+ {"udp4", "golang.org"}: {
+ {IP: IPv4(127, 0, 0, 1)},
+ },
+ {"udp6", "golang.org"}: {
+ {IP: IPv6loopback},
+ },
+ }
+ calls := int32(0)
+ waitCh := make(chan struct{})
+ testHookLookupIP = func(ctx context.Context, fn func(context.Context, string, string) ([]IPAddr, error), network, host string) ([]IPAddr, error) {
+ // We'll block until this is called one time for each different
+ // expected result. This will ensure that the lookup group would wait
+ // for the existing call if it was to be reused.
+ if atomic.AddInt32(&calls, 1) == int32(len(results)) {
+ close(waitCh)
+ }
+ select {
+ case <-waitCh:
+ case <-ctx.Done():
+ return nil, ctx.Err()
+ }
+ return results[[2]string{network, host}], nil
+ }
+
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
+ defer cancel()
+ wg := sync.WaitGroup{}
+ for _, q := range queries {
+ network := q[0]
+ host := q[1]
+ wg.Add(1)
+ go func() {
+ defer wg.Done()
+ gotIPs, err := DefaultResolver.lookupIPAddr(ctx, network, host)
+ if err != nil {
+ t.Errorf("lookupIPAddr(%v, %v): unexpected error: %v", network, host, err)
+ }
+ wantIPs := results[[2]string{network, host}]
+ if !reflect.DeepEqual(gotIPs, wantIPs) {
+ t.Errorf("lookupIPAddr(%v, %v): mismatched IPAddr results\n\tGot: %v\n\tWant: %v", network, host, gotIPs, wantIPs)
+ }
+ }()
+ }
+ wg.Wait()
+}
+
func TestWithUnexpiredValuesPreserved(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go
index 104b7ceaf7d..ba43ea35254 100644
--- a/libgo/go/os/path.go
+++ b/libgo/go/os/path.go
@@ -62,6 +62,7 @@ func MkdirAll(path string, perm FileMode) error {
// It removes everything it can but returns the first error
// it encounters. If the path does not exist, RemoveAll
// returns nil (no error).
+// If there is an error, it will be of type *PathError.
func RemoveAll(path string) error {
return removeAll(path)
}
diff --git a/libgo/go/os/path_unix.go b/libgo/go/os/path_unix.go
index e55301f9765..4864989fb5b 100644
--- a/libgo/go/os/path_unix.go
+++ b/libgo/go/os/path_unix.go
@@ -51,7 +51,7 @@ func splitPath(path string) (string, string) {
// Remove leading directory path
for i--; i >= 0; i-- {
if path[i] == '/' {
- dirname = path[:i+1]
+ dirname = path[:i]
basename = path[i+1:]
break
}
diff --git a/libgo/go/os/removeall_at.go b/libgo/go/os/removeall_at.go
index 512a891017d..6fdd7e828d6 100644
--- a/libgo/go/os/removeall_at.go
+++ b/libgo/go/os/removeall_at.go
@@ -46,13 +46,20 @@ func removeAll(path string) error {
}
defer parent.Close()
- return removeAllFrom(parent, base)
+ if err := removeAllFrom(parent, base); err != nil {
+ if pathErr, ok := err.(*PathError); ok {
+ pathErr.Path = parentDir + string(PathSeparator) + pathErr.Path
+ err = pathErr
+ }
+ return err
+ }
+ return nil
}
-func removeAllFrom(parent *File, path string) error {
+func removeAllFrom(parent *File, base string) error {
parentFd := int(parent.Fd())
// Simple case: if Unlink (aka remove) works, we're done.
- err := unix.Unlinkat(parentFd, path, 0)
+ err := unix.Unlinkat(parentFd, base, 0)
if err == nil || IsNotExist(err) {
return nil
}
@@ -64,21 +71,21 @@ func removeAllFrom(parent *File, path string) error {
// whose contents need to be removed.
// Otherwise just return the error.
if err != syscall.EISDIR && err != syscall.EPERM && err != syscall.EACCES {
- return err
+ return &PathError{"unlinkat", base, err}
}
// Is this a directory we need to recurse into?
var statInfo syscall.Stat_t
- statErr := unix.Fstatat(parentFd, path, &statInfo, unix.AT_SYMLINK_NOFOLLOW)
+ statErr := unix.Fstatat(parentFd, base, &statInfo, unix.AT_SYMLINK_NOFOLLOW)
if statErr != nil {
if IsNotExist(statErr) {
return nil
}
- return statErr
+ return &PathError{"fstatat", base, statErr}
}
if statInfo.Mode&syscall.S_IFMT != syscall.S_IFDIR {
- // Not a directory; return the error from the Remove.
- return err
+ // Not a directory; return the error from the unix.Unlinkat.
+ return &PathError{"unlinkat", base, err}
}
// Remove the directory's entries.
@@ -87,12 +94,12 @@ func removeAllFrom(parent *File, path string) error {
const request = 1024
// Open the directory to recurse into
- file, err := openFdAt(parentFd, path)
+ file, err := openFdAt(parentFd, base)
if err != nil {
if IsNotExist(err) {
return nil
}
- recurseErr = err
+ recurseErr = &PathError{"openfdat", base, err}
break
}
@@ -103,12 +110,15 @@ func removeAllFrom(parent *File, path string) error {
if IsNotExist(readErr) {
return nil
}
- return readErr
+ return &PathError{"readdirnames", base, readErr}
}
for _, name := range names {
err := removeAllFrom(file, name)
if err != nil {
+ if pathErr, ok := err.(*PathError); ok {
+ pathErr.Path = base + string(PathSeparator) + pathErr.Path
+ }
recurseErr = err
}
}
@@ -127,7 +137,7 @@ func removeAllFrom(parent *File, path string) error {
}
// Remove the directory itself.
- unlinkError := unix.Unlinkat(parentFd, path, unix.AT_REMOVEDIR)
+ unlinkError := unix.Unlinkat(parentFd, base, unix.AT_REMOVEDIR)
if unlinkError == nil || IsNotExist(unlinkError) {
return nil
}
@@ -135,7 +145,7 @@ func removeAllFrom(parent *File, path string) error {
if recurseErr != nil {
return recurseErr
}
- return unlinkError
+ return &PathError{"unlinkat", base, unlinkError}
}
// openFdAt opens path relative to the directory in fd.
@@ -157,7 +167,7 @@ func openFdAt(dirfd int, name string) (*File, error) {
continue
}
- return nil, &PathError{"openat", name, e}
+ return nil, e
}
if !supportsCloseOnExec {
diff --git a/libgo/go/os/removeall_test.go b/libgo/go/os/removeall_test.go
index 21371d8776a..945a38e8e06 100644
--- a/libgo/go/os/removeall_test.go
+++ b/libgo/go/os/removeall_test.go
@@ -294,7 +294,7 @@ func TestRemoveReadOnlyDir(t *testing.T) {
}
// Issue #29983.
-func TestRemoveAllButReadOnly(t *testing.T) {
+func TestRemoveAllButReadOnlyAndPathError(t *testing.T) {
switch runtime.GOOS {
case "nacl", "js", "windows":
t.Skipf("skipping test on %s", runtime.GOOS)
@@ -355,10 +355,21 @@ func TestRemoveAllButReadOnly(t *testing.T) {
defer Chmod(d, 0777)
}
- if err := RemoveAll(tempDir); err == nil {
+ err = RemoveAll(tempDir)
+ if err == nil {
t.Fatal("RemoveAll succeeded unexpectedly")
}
+ // The error should be of type *PathError.
+ // see issue 30491 for details.
+ if pathErr, ok := err.(*PathError); ok {
+ if g, w := pathErr.Path, filepath.Join(tempDir, "b", "y"); g != w {
+ t.Errorf("got %q, expected pathErr.path %q", g, w)
+ }
+ } else {
+ t.Errorf("got %T, expected *os.PathError", err)
+ }
+
for _, dir := range dirs {
_, err := Stat(filepath.Join(tempDir, dir))
if inReadonly(dir) {
diff --git a/libgo/go/runtime/runtime-lldb_test.go b/libgo/go/runtime/runtime-lldb_test.go
index fe3a0eb90d8..08d6a34f50c 100644
--- a/libgo/go/runtime/runtime-lldb_test.go
+++ b/libgo/go/runtime/runtime-lldb_test.go
@@ -139,6 +139,7 @@ func TestLldbPython(t *testing.T) {
if final := os.Getenv("GOROOT_FINAL"); final != "" && runtime.GOROOT() != final {
t.Skip("gdb test can fail with GOROOT_FINAL pending")
}
+ testenv.SkipFlaky(t, 31188)
checkLldbPython(t)
diff --git a/libgo/go/syscall/security_windows.go b/libgo/go/syscall/security_windows.go
index ae8b3a17bfb..db80d98a084 100644
--- a/libgo/go/syscall/security_windows.go
+++ b/libgo/go/syscall/security_windows.go
@@ -290,6 +290,7 @@ type Tokenprimarygroup struct {
//sys OpenProcessToken(h Handle, access uint32, token *Token) (err error) = advapi32.OpenProcessToken
//sys GetTokenInformation(t Token, infoClass uint32, info *byte, infoLen uint32, returnedLen *uint32) (err error) = advapi32.GetTokenInformation
//sys GetUserProfileDirectory(t Token, dir *uint16, dirLen *uint32) (err error) = userenv.GetUserProfileDirectoryW
+//sys getSystemDirectory(dir *uint16, dirLen uint32) (len uint32, err error) = kernel32.GetSystemDirectoryW
// An access token contains the security information for a logon session.
// The system creates an access token when a user logs on, and every