This patch updates libgo to the 1.12.2 release.  Bootstrapped and ran
Go testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 270212)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -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.
Index: libgo/MERGE
===================================================================
--- libgo/MERGE (revision 270212)
+++ libgo/MERGE (working copy)
@@ -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.
Index: libgo/VERSION
===================================================================
--- libgo/VERSION       (revision 270212)
+++ libgo/VERSION       (working copy)
@@ -1 +1 @@
-go1.12.1
+go1.12.2
Index: libgo/go/cmd/go/internal/load/pkg.go
===================================================================
--- libgo/go/cmd/go/internal/load/pkg.go        (revision 270212)
+++ libgo/go/cmd/go/internal/load/pkg.go        (working copy)
@@ -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,
                }
                _, 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,
                        // 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 {
Index: libgo/go/cmd/go/internal/load/test.go
===================================================================
--- libgo/go/cmd/go/internal/load/test.go       (revision 270212)
+++ libgo/go/cmd/go/internal/load/test.go       (working copy)
@@ -268,17 +268,8 @@ func GetTestPackagesFor(p *Package, cove
        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, ptes
 
                // 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()
                }
Index: libgo/go/cmd/go/internal/test/test.go
===================================================================
--- libgo/go/cmd/go/internal/test/test.go       (revision 270212)
+++ libgo/go/cmd/go/internal/test/test.go       (working copy)
@@ -805,7 +805,7 @@ func builderTest(b *work.Builder, p *loa
        if p.ImportPath == "command-line-arguments" {
                elem = p.Name
        } else {
-               _, elem = path.Split(p.ImportPath)
+               elem = load.DefaultExecName(p.ImportPath)
        }
        testBinary := elem + ".test"
 
Index: libgo/go/cmd/go/internal/work/build.go
===================================================================
--- libgo/go/cmd/go/internal/work/build.go      (revision 270212)
+++ libgo/go/cmd/go/internal/work/build.go      (working copy)
@@ -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 []
        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,
        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)
Index: libgo/go/cmd/go/internal/work/exec.go
===================================================================
--- libgo/go/cmd/go/internal/work/exec.go       (revision 270212)
+++ libgo/go/cmd/go/internal/work/exec.go       (working copy)
@@ -214,6 +214,7 @@ func (b *Builder) buildActionID(a *Actio
        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 {
Index: libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt
===================================================================
--- libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt   (revision 
270212)
+++ libgo/go/cmd/go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt   (working copy)
@@ -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) {}
Index: libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt
===================================================================
--- libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt     
(nonexistent)
+++ libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt     
(working copy)
@@ -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) {}
Index: libgo/go/internal/poll/fd_windows.go
===================================================================
--- libgo/go/internal/poll/fd_windows.go        (revision 270212)
+++ libgo/go/internal/poll/fd_windows.go        (working copy)
@@ -660,6 +660,10 @@ func (fd *FD) Write(buf []byte) (int, er
                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, er
                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 {
Index: libgo/go/net/http/httputil/reverseproxy.go
===================================================================
--- libgo/go/net/http/httputil/reverseproxy.go  (revision 270212)
+++ libgo/go/net/http/httputil/reverseproxy.go  (working copy)
@@ -389,6 +389,11 @@ func (p *ReverseProxy) copyResponse(dst
                                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
                }
        }
Index: libgo/go/net/http/httputil/reverseproxy_test.go
===================================================================
--- libgo/go/net/http/httputil/reverseproxy_test.go     (revision 270212)
+++ libgo/go/net/http/httputil/reverseproxy_test.go     (working copy)
@@ -9,6 +9,7 @@ package httputil
 import (
        "bufio"
        "bytes"
+       "context"
        "errors"
        "fmt"
        "io"
@@ -317,6 +318,47 @@ func TestReverseProxyFlushInterval(t *te
        }
 }
 
+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"
 
Index: libgo/go/net/lookup.go
===================================================================
--- libgo/go/net/lookup.go      (revision 270212)
+++ libgo/go/net/lookup.go      (working copy)
@@ -262,8 +262,9 @@ func (r *Resolver) lookupIPAddr(ctx cont
        // 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 cont
                // 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() {
Index: libgo/go/net/lookup_test.go
===================================================================
--- libgo/go/net/lookup_test.go (revision 270212)
+++ libgo/go/net/lookup_test.go (working copy)
@@ -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 *te
 
        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 *te
                        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 TestLookupIPAddrPreservesContextVal
        }
 }
 
+// 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())
 
Index: libgo/go/os/path.go
===================================================================
--- libgo/go/os/path.go (revision 270212)
+++ libgo/go/os/path.go (working copy)
@@ -62,6 +62,7 @@ func MkdirAll(path string, perm FileMode
 // 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)
 }
Index: libgo/go/os/path_unix.go
===================================================================
--- libgo/go/os/path_unix.go    (revision 270212)
+++ libgo/go/os/path_unix.go    (working copy)
@@ -51,7 +51,7 @@ func splitPath(path string) (string, str
        // Remove leading directory path
        for i--; i >= 0; i-- {
                if path[i] == '/' {
-                       dirname = path[:i+1]
+                       dirname = path[:i]
                        basename = path[i+1:]
                        break
                }
Index: libgo/go/os/removeall_at.go
===================================================================
--- libgo/go/os/removeall_at.go (revision 270212)
+++ libgo/go/os/removeall_at.go (working copy)
@@ -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 st
        // 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 st
                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 st
                        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 st
        }
 
        // 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 st
        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) (*
                        continue
                }
 
-               return nil, &PathError{"openat", name, e}
+               return nil, e
        }
 
        if !supportsCloseOnExec {
Index: libgo/go/os/removeall_test.go
===================================================================
--- libgo/go/os/removeall_test.go       (revision 270212)
+++ libgo/go/os/removeall_test.go       (working copy)
@@ -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
                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) {
Index: libgo/go/runtime/runtime-lldb_test.go
===================================================================
--- libgo/go/runtime/runtime-lldb_test.go       (revision 270212)
+++ libgo/go/runtime/runtime-lldb_test.go       (working copy)
@@ -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)
 
Index: libgo/go/syscall/security_windows.go
===================================================================
--- libgo/go/syscall/security_windows.go        (revision 270212)
+++ libgo/go/syscall/security_windows.go        (working copy)
@@ -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

Reply via email to