From 9195aa172bbc20627f23bfb1612180c83a0a7bab Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 19 Mar 2019 14:00:59 +0000 Subject: libgo: fix build on AIX Since aix/ppc64 has been added to GC toolchain, a mix between new and old files were created in gcc toolchain. This commit corrects this merge for aix/ppc64 and aix/ppc. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/167658 From-SVN: r269797 --- libgo/go/archive/tar/stat_actime1.go | 2 +- .../lockedfile/internal/filelock/filelock_fcntl.go | 6 ++- libgo/go/internal/syscall/unix/at_largefile.go | 2 +- libgo/go/internal/syscall/unix/at_regfile.go | 1 - libgo/go/internal/syscall/unix/ioctl_aix.go | 13 ++----- libgo/go/net/interface_aix.go | 8 ++-- libgo/go/net/interface_stub.go | 2 +- libgo/go/net/sockoptip_aix.go | 15 -------- libgo/go/os/dir_gccgo.go | 3 -- libgo/go/os/dir_libc64_gccgo.go | 3 ++ libgo/go/os/dir_libc_gccgo.go | 3 ++ libgo/go/os/sys_aix.go | 26 ------------- libgo/go/runtime/malloc.go | 6 +-- libgo/go/runtime/mem_gccgo.go | 5 +++ libgo/go/runtime/netpoll_aix.go | 1 - libgo/go/runtime/os_aix.go | 17 +++++--- libgo/go/runtime/stubs2.go | 1 - libgo/go/runtime/timestub2.go | 2 - libgo/go/syscall/exec_aix_test.go | 37 ------------------ libgo/go/syscall/exec_unix.go | 6 +-- libgo/go/syscall/flock_aix.go | 18 --------- libgo/go/syscall/libcall_aix.go | 6 +++ libgo/go/syscall/syscall_funcs.go | 45 ++++++++++++++++++++++ libgo/go/syscall/syscall_funcs_stubs.go | 29 ++++++++++++++ libgo/go/syscall/syscall_stubs.go | 29 -------------- libgo/go/syscall/syscall_unix.go | 38 ------------------ 26 files changed, 123 insertions(+), 201 deletions(-) delete mode 100644 libgo/go/net/sockoptip_aix.go delete mode 100644 libgo/go/os/sys_aix.go delete mode 100644 libgo/go/syscall/exec_aix_test.go delete mode 100644 libgo/go/syscall/flock_aix.go create mode 100644 libgo/go/syscall/syscall_funcs.go create mode 100644 libgo/go/syscall/syscall_funcs_stubs.go delete mode 100644 libgo/go/syscall/syscall_stubs.go (limited to 'libgo/go') diff --git a/libgo/go/archive/tar/stat_actime1.go b/libgo/go/archive/tar/stat_actime1.go index e2c79a5..2a7f7f3 100644 --- a/libgo/go/archive/tar/stat_actime1.go +++ b/libgo/go/archive/tar/stat_actime1.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build hurd linux dragonfly openbsd solaris +// +build aix hurd linux dragonfly openbsd solaris package tar diff --git a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go index 2831975..a14362b 100644 --- a/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go +++ b/libgo/go/cmd/go/internal/lockedfile/internal/filelock/filelock_fcntl.go @@ -35,7 +35,9 @@ const ( writeLock lockType = syscall.F_WRLCK ) -type inode = uint64 // type of syscall.Stat_t.Ino +// type of syscall.Stat_t.Ino for 64 bits architectures. +// For 32 bits architecture, it's easier to cast it instead. +type inode = uint64 type inodeLock struct { owner File @@ -59,7 +61,7 @@ func lock(f File, lt lockType) (err error) { if err != nil { return err } - ino := fi.Sys().(*syscall.Stat_t).Ino + ino := uint64(fi.Sys().(*syscall.Stat_t).Ino) mu.Lock() if i, dup := inodes[f]; dup && i != ino { diff --git a/libgo/go/internal/syscall/unix/at_largefile.go b/libgo/go/internal/syscall/unix/at_largefile.go index 5318d23..82e0dcf 100644 --- a/libgo/go/internal/syscall/unix/at_largefile.go +++ b/libgo/go/internal/syscall/unix/at_largefile.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix hurd linux solaris,386 solaris,sparc +// +build hurd linux solaris,386 solaris,sparc package unix diff --git a/libgo/go/internal/syscall/unix/at_regfile.go b/libgo/go/internal/syscall/unix/at_regfile.go index 004c801..14fdb70 100644 --- a/libgo/go/internal/syscall/unix/at_regfile.go +++ b/libgo/go/internal/syscall/unix/at_regfile.go @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !aix // +build !hurd // +build !linux // +build !solaris !386 diff --git a/libgo/go/internal/syscall/unix/ioctl_aix.go b/libgo/go/internal/syscall/unix/ioctl_aix.go index 19d56c3..af105d6 100644 --- a/libgo/go/internal/syscall/unix/ioctl_aix.go +++ b/libgo/go/internal/syscall/unix/ioctl_aix.go @@ -9,17 +9,12 @@ import ( "unsafe" ) -//go:cgo_import_dynamic libc_ioctl ioctl "libc.a/shr_64.o" -//go:linkname libc_ioctl libc_ioctl -var libc_ioctl uintptr - -// Implemented in syscall/syscall_aix.go. -func syscall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.Errno) +//extern __go_ioctl_ptr +func ioctl(int32, int32, unsafe.Pointer) int32 func Ioctl(fd int, cmd int, args uintptr) (err error) { - _, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_ioctl)), 3, uintptr(fd), uintptr(cmd), uintptr(args), 0, 0, 0) - if e1 != 0 { - err = e1 + if ioctl(int32(fd), int32(cmd), unsafe.Pointer(args)) < 0 { + return syscall.GetErrno() } return } diff --git a/libgo/go/net/interface_aix.go b/libgo/go/net/interface_aix.go index 9a8b5bb..1fe9bba 100644 --- a/libgo/go/net/interface_aix.go +++ b/libgo/go/net/interface_aix.go @@ -32,6 +32,8 @@ const _RTAX_NETMASK = 2 const _RTAX_IFA = 5 const _RTAX_MAX = 8 +const _SIOCGIFMTU = -0x3fd796aa + func getIfList() ([]byte, error) { needed, err := syscall.Getkerninfo(_KINFO_RT_IFLIST, 0, 0, 0) if err != nil { @@ -62,7 +64,7 @@ func interfaceTable(ifindex int) ([]Interface, error) { } if ifm.Type == syscall.RTM_IFINFO { if ifindex == 0 || ifindex == int(ifm.Index) { - sdl := (*rawSockaddrDatalink)(unsafe.Pointer(&tab[syscall.SizeofIfMsghdr])) + sdl := (*rawSockaddrDatalink)(unsafe.Pointer(&tab[unsafe.Sizeof(syscall.IfMsgHdr)])) ifi := &Interface{Index: int(ifm.Index), Flags: linkFlags(ifm.Flags)} ifi.Name = string(sdl.Data[:sdl.Nlen]) @@ -75,7 +77,7 @@ func interfaceTable(ifindex int) ([]Interface, error) { if err != nil { return nil, err } - err = unix.Ioctl(sock, syscall.SIOCGIFMTU, uintptr(unsafe.Pointer(ifr))) + err = unix.Ioctl(sock, _SIOCGIFMTU, uintptr(unsafe.Pointer(ifr))) if err != nil { return nil, err } @@ -131,7 +133,7 @@ func interfaceAddrTable(ifi *Interface) ([]Addr, error) { if ifm.Type == syscall.RTM_NEWADDR { if ifi == nil || ifi.Index == int(ifm.Index) { mask := ifm.Addrs - off := uint(syscall.SizeofIfMsghdr) + off := uint(unsafe.Sizeof(syscall.IfMsgHdr)) var iprsa, nmrsa *syscall.RawSockaddr for i := uint(0); i < _RTAX_MAX; i++ { diff --git a/libgo/go/net/interface_stub.go b/libgo/go/net/interface_stub.go index 0b3580e..d8afd5e 100644 --- a/libgo/go/net/interface_stub.go +++ b/libgo/go/net/interface_stub.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build aix nacl hurd js,wasm +// +build nacl hurd js,wasm package net diff --git a/libgo/go/net/sockoptip_aix.go b/libgo/go/net/sockoptip_aix.go deleted file mode 100644 index 1e28fe6..0000000 --- a/libgo/go/net/sockoptip_aix.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2017 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. - -package net - -import "syscall" - -func setIPv4MulticastInterface(fd *netFD, ifi *Interface) error { - return syscall.ENOPROTOOPT -} - -func setIPv4MulticastLoopback(fd *netFD, v bool) error { - return syscall.ENOPROTOOPT -} diff --git a/libgo/go/os/dir_gccgo.go b/libgo/go/os/dir_gccgo.go index 60f70aa..ad77a40 100644 --- a/libgo/go/os/dir_gccgo.go +++ b/libgo/go/os/dir_gccgo.go @@ -16,9 +16,6 @@ import ( //extern pathconf func libc_pathconf(*byte, int) int -//extern fdopendir -func libc_fdopendir(int32) *syscall.DIR - func clen(n []byte) int { for i := 0; i < len(n); i++ { if n[i] == 0 { diff --git a/libgo/go/os/dir_libc64_gccgo.go b/libgo/go/os/dir_libc64_gccgo.go index dc3ba7f..3582243 100644 --- a/libgo/go/os/dir_libc64_gccgo.go +++ b/libgo/go/os/dir_libc64_gccgo.go @@ -10,3 +10,6 @@ import "syscall" //extern closedir64 func libc_closedir(*syscall.DIR) int + +//extern fdopendir64 +func libc_fdopendir(int32) *syscall.DIR diff --git a/libgo/go/os/dir_libc_gccgo.go b/libgo/go/os/dir_libc_gccgo.go index b46eb4c..a3be43b 100644 --- a/libgo/go/os/dir_libc_gccgo.go +++ b/libgo/go/os/dir_libc_gccgo.go @@ -10,3 +10,6 @@ import "syscall" //extern closedir func libc_closedir(*syscall.DIR) int + +//extern fdopendir +func libc_fdopendir(int32) *syscall.DIR diff --git a/libgo/go/os/sys_aix.go b/libgo/go/os/sys_aix.go deleted file mode 100644 index 53a40f2..0000000 --- a/libgo/go/os/sys_aix.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2018 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. - -package os - -import "syscall" - -// gethostname syscall cannot be used because it also returns the domain. -// Therefore, hostname is retrieve with uname syscall and the Nodename field. - -func hostname() (name string, err error) { - var u syscall.Utsname - if errno := syscall.Uname(&u); errno != nil { - return "", NewSyscallError("uname", errno) - } - b := make([]byte, len(u.Nodename)) - i := 0 - for ; i < len(u.Nodename); i++ { - if u.Nodename[i] == 0 { - break - } - b[i] = byte(u.Nodename[i]) - } - return string(b[:i]), nil -} diff --git a/libgo/go/runtime/malloc.go b/libgo/go/runtime/malloc.go index b6a7ee1..c0b4caa 100644 --- a/libgo/go/runtime/malloc.go +++ b/libgo/go/runtime/malloc.go @@ -218,7 +218,7 @@ const ( // we further limit it to 31 bits. // // WebAssembly currently has a limit of 4GB linear memory. - heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosAix))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 60*sys.GoosAix + heapAddrBits = (_64bit*(1-sys.GoarchWasm)*(1-sys.GoosAix))*48 + (1-_64bit+sys.GoarchWasm)*(32-(sys.GoarchMips+sys.GoarchMipsle)) + 60*(sys.GoosAix*_64bit) // maxAlloc is the maximum size of an allocation. On 64-bit, // it's theoretically possible to allocate 1<= 1e9 { - ts.tv_sec++ - ts.tv_nsec -= 1e9 + + sec := int64(ts.tv_sec) + ns/1e9 + nsec := int64(ts.tv_nsec) + ns%1e9 + if nsec >= 1e9 { + sec++ + nsec -= 1e9 + } + if sec != int64(timespec_sec_t(sec)) { + // Handle overflows (timespec_sec_t is 32-bit in 32-bit applications) + sec = 1<<31 - 1 } + ts.tv_sec = timespec_sec_t(sec) + ts.tv_nsec = timespec_nsec_t(nsec) if sem_timedwait((*semt)(unsafe.Pointer(_m_.mos.waitsema)), &ts) != 0 { err := errno() diff --git a/libgo/go/runtime/stubs2.go b/libgo/go/runtime/stubs2.go index 304c8e4..1cb910c 100644 --- a/libgo/go/runtime/stubs2.go +++ b/libgo/go/runtime/stubs2.go @@ -7,7 +7,6 @@ // +build !nacl // +build !js // +build !darwin -// +build !aix package runtime diff --git a/libgo/go/runtime/timestub2.go b/libgo/go/runtime/timestub2.go index 00c2c55..7a28603 100644 --- a/libgo/go/runtime/timestub2.go +++ b/libgo/go/runtime/timestub2.go @@ -5,8 +5,6 @@ // +build !darwin // +build !windows // +build !freebsd -// +build !aix - package runtime func walltime() (sec int64, nsec int32) diff --git a/libgo/go/syscall/exec_aix_test.go b/libgo/go/syscall/exec_aix_test.go deleted file mode 100644 index 22b752c..0000000 --- a/libgo/go/syscall/exec_aix_test.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2015 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 aix - -package syscall - -import "unsafe" - -//go:cgo_import_dynamic libc_Getpgid getpgid "libc.a/shr_64.o" -//go:cgo_import_dynamic libc_Getpgrp getpgrp "libc.a/shr_64.o" - -//go:linkname libc_Getpgid libc_Getpgid -//go:linkname libc_Getpgrp libc_Getpgrp - -var ( - libc_Getpgid, - libc_Getpgrp libcFunc -) - -func Getpgid(pid int) (pgid int, err error) { - r0, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_Getpgid)), 1, uintptr(pid), 0, 0, 0, 0, 0) - pgid = int(r0) - if e1 != 0 { - err = e1 - } - return -} - -func Getpgrp() (pgrp int) { - r0, _, _ := syscall6(uintptr(unsafe.Pointer(&libc_Getpgrp)), 0, 0, 0, 0, 0, 0, 0) - pgrp = int(r0) - return -} - -var Ioctl = ioctl diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go index bad2ce4..ec21f80 100644 --- a/libgo/go/syscall/exec_unix.go +++ b/libgo/go/syscall/exec_unix.go @@ -299,7 +299,6 @@ func runtime_AfterExec() // execveLibc is non-nil on OS using libc syscall, set to execve in exec_libc.go; this // avoids a build dependency for other platforms. -var execveLibc func(path uintptr, argv uintptr, envp uintptr) Errno var execveDarwin func(path *byte, argv **byte, envp **byte) error // Exec invokes the execve(2) system call. @@ -321,10 +320,7 @@ func Exec(argv0 string, argv []string, envv []string) (err error) { var err1 error if runtime.GOOS == "solaris" || runtime.GOOS == "aix" || runtime.GOOS == "hurd" { // RawSyscall should never be used on Solaris or AIX. - err1 = execveLibc( - uintptr(unsafe.Pointer(argv0p)), - uintptr(unsafe.Pointer(&argvp[0])), - uintptr(unsafe.Pointer(&envvp[0]))) + err1 = raw_execve(argv0p, &argvp[0], &envvp[0]) } else if runtime.GOOS == "darwin" { // Similarly on Darwin. err1 = execveDarwin(argv0p, &argvp[0], &envvp[0]) diff --git a/libgo/go/syscall/flock_aix.go b/libgo/go/syscall/flock_aix.go deleted file mode 100644 index c9eab43..0000000 --- a/libgo/go/syscall/flock_aix.go +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2018 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. - -package syscall - -import "unsafe" - -// On AIX, there is no flock() system call. - -// FcntlFlock performs a fcntl syscall for the F_GETLK, F_SETLK or F_SETLKW command. -func FcntlFlock(fd uintptr, cmd int, lk *Flock_t) (err error) { - _, _, e1 := syscall6(uintptr(unsafe.Pointer(&libc_fcntl)), 3, uintptr(fd), uintptr(cmd), uintptr(unsafe.Pointer(lk)), 0, 0, 0) - if e1 != 0 { - err = errnoErr(e1) - } - return -} diff --git a/libgo/go/syscall/libcall_aix.go b/libgo/go/syscall/libcall_aix.go index 072f92a..8d9f59e 100644 --- a/libgo/go/syscall/libcall_aix.go +++ b/libgo/go/syscall/libcall_aix.go @@ -10,6 +10,9 @@ import ( "unsafe" ) +// For exec_unix.go. +const SYS_EXECVE = 0 + //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) //open64at(dirfd _C_int, path *byte, flags _C_int, mode Mode_t) _C_int @@ -139,3 +142,6 @@ func ReadDirent(fd int, buf []byte) (n int, err error) { func Unlinkat(dirfd int, path string) (err error) { return unlinkat(dirfd, path, 0) } + +//sys Getkerninfo(op int32, where uintptr, size uintptr, arg int64) (i int32, err error) +//getkerninfo(op _C_int, where *byte, size *byte, arg _C_long) _C_int diff --git a/libgo/go/syscall/syscall_funcs.go b/libgo/go/syscall/syscall_funcs.go new file mode 100644 index 0000000..4b1ee32 --- /dev/null +++ b/libgo/go/syscall/syscall_funcs.go @@ -0,0 +1,45 @@ +// Copyright 2009 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 darwin dragonfly freebsd hurd linux netbsd openbsd solaris + +package syscall + +//extern __go_syscall6 +func syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr + +// Do a system call. We look at the size of uintptr to see how to pass +// the arguments, so that we don't pass a 64-bit value when the function +// expects a 32-bit one. +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + Entersyscall() + SetErrno(0) + r := syscall6(trap, a1, a2, a3, 0, 0, 0) + err = GetErrno() + Exitsyscall() + return r, 0, err +} + +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + Entersyscall() + SetErrno(0) + r := syscall6(trap, a1, a2, a3, a4, a5, a6) + err = GetErrno() + Exitsyscall() + return r, 0, err +} + +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + SetErrno(0) + r := syscall6(trap, a1, a2, a3, 0, 0, 0) + err = GetErrno() + return r, 0, err +} + +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + SetErrno(0) + r := syscall6(trap, a1, a2, a3, a4, a5, a6) + err = GetErrno() + return r, 0, err +} diff --git a/libgo/go/syscall/syscall_funcs_stubs.go b/libgo/go/syscall/syscall_funcs_stubs.go new file mode 100644 index 0000000..c68ab26 --- /dev/null +++ b/libgo/go/syscall/syscall_funcs_stubs.go @@ -0,0 +1,29 @@ +// Copyright 2010 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 aix rtems + +// These are stubs. + +package syscall + +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + z := -1 + return uintptr(z), 0, ENOSYS +} + +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + z := -1 + return uintptr(z), 0, ENOSYS +} + +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { + z := -1 + return uintptr(z), 0, ENOSYS +} + +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { + z := -1 + return uintptr(z), 0, ENOSYS +} diff --git a/libgo/go/syscall/syscall_stubs.go b/libgo/go/syscall/syscall_stubs.go deleted file mode 100644 index 00288ee..0000000 --- a/libgo/go/syscall/syscall_stubs.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2010 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 rtems - -// These are stubs. - -package syscall - -func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - z := -1 - return uintptr(z), 0, uintptr(ENOSYS) -} - -func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - z := -1 - return uintptr(z), 0, uintptr(ENOSYS) -} - -func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - z := -1 - return uintptr(z), 0, uintptr(ENOSYS) -} - -func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - z := -1 - return uintptr(z), 0, uintptr(ENOSYS) -} diff --git a/libgo/go/syscall/syscall_unix.go b/libgo/go/syscall/syscall_unix.go index b786dc5..ec8f343 100644 --- a/libgo/go/syscall/syscall_unix.go +++ b/libgo/go/syscall/syscall_unix.go @@ -19,9 +19,6 @@ var ( Stderr = 2 ) -//extern __go_syscall6 -func syscall6(trap uintptr, a1, a2, a3, a4, a5, a6 uintptr) uintptr - const ( darwin64Bit = runtime.GOOS == "darwin" && sizeofPtr == 8 dragonfly64Bit = runtime.GOOS == "dragonfly" && sizeofPtr == 8 @@ -29,41 +26,6 @@ const ( solaris64Bit = runtime.GOOS == "solaris" && sizeofPtr == 8 ) -// Do a system call. We look at the size of uintptr to see how to pass -// the arguments, so that we don't pass a 64-bit value when the function -// expects a 32-bit one. -func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { - Entersyscall() - SetErrno(0) - r := syscall6(trap, a1, a2, a3, 0, 0, 0) - err = GetErrno() - Exitsyscall() - return r, 0, err -} - -func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { - Entersyscall() - SetErrno(0) - r := syscall6(trap, a1, a2, a3, a4, a5, a6) - err = GetErrno() - Exitsyscall() - return r, 0, err -} - -func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno) { - SetErrno(0) - r := syscall6(trap, a1, a2, a3, 0, 0, 0) - err = GetErrno() - return r, 0, err -} - -func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno) { - SetErrno(0) - r := syscall6(trap, a1, a2, a3, a4, a5, a6) - err = GetErrno() - return r, 0, err -} - // clen returns the index of the first NULL byte in n or len(n) if n contains no NULL byte. func clen(n []byte) int { for i := 0; i < len(n); i++ { -- cgit v1.1 From ea5ac5a69b4b474bb221051e705f98d8599253fa Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 19 Mar 2019 18:42:43 +0000 Subject: compiler,runtime: pass old slice's ptr/len/cap by value to growslice In the C calling convention, on AMD64, and probably a number of other architectures, a 3-word struct argument is passed on stack. This is less efficient than passing in three registers. Further, this may affect the code generation in other part of the program, even if the function is not actually called. Slices are common in Go and append is a common slice operation, which calls growslice in the growing path. To improve the code generation, pass the slice header's three fields as separate values, instead of a struct, to growslice. The drawback is that this makes the runtime implementation slightly diverges from the gc runtime. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/168277 From-SVN: r269811 --- libgo/go/runtime/slice.go | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'libgo/go') diff --git a/libgo/go/runtime/slice.go b/libgo/go/runtime/slice.go index 335532d..9137951 100644 --- a/libgo/go/runtime/slice.go +++ b/libgo/go/runtime/slice.go @@ -77,31 +77,31 @@ func makeslice64(et *_type, len64, cap64 int64) unsafe.Pointer { // and it returns a new slice with at least that capacity, with the old data // copied into it. // The new slice's length is set to the requested capacity. -func growslice(et *_type, old slice, cap int) slice { +func growslice(et *_type, oldarray unsafe.Pointer, oldlen, oldcap, cap int) slice { if raceenabled { callerpc := getcallerpc() - racereadrangepc(old.array, uintptr(old.len*int(et.size)), callerpc, funcPC(growslice)) + racereadrangepc(oldarray, uintptr(oldlen*int(et.size)), callerpc, funcPC(growslice)) } if msanenabled { - msanread(old.array, uintptr(old.len*int(et.size))) + msanread(oldarray, uintptr(oldlen*int(et.size))) } - if cap < old.cap { + if cap < oldcap { panic(errorString("growslice: cap out of range")) } if et.size == 0 { // append should not create a slice with nil pointer but non-zero len. - // We assume that append doesn't need to preserve old.array in this case. + // We assume that append doesn't need to preserve oldarray in this case. return slice{unsafe.Pointer(&zerobase), cap, cap} } - newcap := old.cap + newcap := oldcap doublecap := newcap + newcap if cap > doublecap { newcap = cap } else { - if old.len < 1024 { + if oldlen < 1024 { newcap = doublecap } else { // Check 0 < newcap to detect overflow @@ -125,13 +125,13 @@ func growslice(et *_type, old slice, cap int) slice { // For powers of 2, use a variable shift. switch { case et.size == 1: - lenmem = uintptr(old.len) + lenmem = uintptr(oldlen) newlenmem = uintptr(cap) capmem = roundupsize(uintptr(newcap)) overflow = uintptr(newcap) > maxAlloc newcap = int(capmem) case et.size == sys.PtrSize: - lenmem = uintptr(old.len) * sys.PtrSize + lenmem = uintptr(oldlen) * sys.PtrSize newlenmem = uintptr(cap) * sys.PtrSize capmem = roundupsize(uintptr(newcap) * sys.PtrSize) overflow = uintptr(newcap) > maxAlloc/sys.PtrSize @@ -144,13 +144,13 @@ func growslice(et *_type, old slice, cap int) slice { } else { shift = uintptr(sys.Ctz32(uint32(et.size))) & 31 } - lenmem = uintptr(old.len) << shift + lenmem = uintptr(oldlen) << shift newlenmem = uintptr(cap) << shift capmem = roundupsize(uintptr(newcap) << shift) overflow = uintptr(newcap) > (maxAlloc >> shift) newcap = int(capmem >> shift) default: - lenmem = uintptr(old.len) * et.size + lenmem = uintptr(oldlen) * et.size newlenmem = uintptr(cap) * et.size capmem, overflow = math.MulUintptr(et.size, uintptr(newcap)) capmem = roundupsize(capmem) @@ -177,19 +177,19 @@ func growslice(et *_type, old slice, cap int) slice { var p unsafe.Pointer if et.kind&kindNoPointers != 0 { p = mallocgc(capmem, nil, false) - // The append() that calls growslice is going to overwrite from old.len to cap (which will be the new length). + // The append() that calls growslice is going to overwrite from oldlen to cap (which will be the new length). // Only clear the part that will not be overwritten. memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem) } else { // Note: can't use rawmem (which avoids zeroing of memory), because then GC can scan uninitialized memory. p = mallocgc(capmem, et, true) if writeBarrier.enabled { - // Only shade the pointers in old.array since we know the destination slice p + // Only shade the pointers in oldarray since we know the destination slice p // only contains nil pointers because it has been cleared during alloc. - bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem) + bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(oldarray), lenmem) } } - memmove(p, old.array, lenmem) + memmove(p, oldarray, lenmem) return slice{p, cap, newcap} } -- cgit v1.1 From 04862afe9f5c54a420823f95bb6ae152eec64b8b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 8 Apr 2019 18:36:25 +0000 Subject: libgo: update to Go 1.12.2 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/170706 From-SVN: r270214 --- libgo/go/cmd/go/internal/load/pkg.go | 53 ++++++++----- libgo/go/cmd/go/internal/load/test.go | 23 +++--- libgo/go/cmd/go/internal/test/test.go | 2 +- libgo/go/cmd/go/internal/work/build.go | 5 +- libgo/go/cmd/go/internal/work/exec.go | 1 + .../go/testdata/mod/rsc.io_fortune_v2_v2.0.0.txt | 6 ++ .../script/cover_pkgall_multiple_mains.txt | 43 +++++++++++ libgo/go/internal/poll/fd_windows.go | 6 +- libgo/go/net/http/httputil/reverseproxy.go | 5 ++ libgo/go/net/http/httputil/reverseproxy_test.go | 42 ++++++++++ libgo/go/net/lookup.go | 5 +- libgo/go/net/lookup_test.go | 89 ++++++++++++++++++---- libgo/go/os/path.go | 1 + libgo/go/os/path_unix.go | 2 +- libgo/go/os/removeall_at.go | 38 +++++---- libgo/go/os/removeall_test.go | 15 +++- libgo/go/runtime/runtime-lldb_test.go | 1 + libgo/go/syscall/security_windows.go | 1 + 18 files changed, 267 insertions(+), 71 deletions(-) create mode 100644 libgo/go/cmd/go/testdata/script/cover_pkgall_multiple_mains.txt (limited to 'libgo/go') diff --git a/libgo/go/cmd/go/internal/load/pkg.go b/libgo/go/cmd/go/internal/load/pkg.go index 543250e..5e511db 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 c0e0667..7385c4e 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 332f312..b72eace 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 145b875..ed66df2 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 fc052b3..5302724 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 cfa91f0..3acd637 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 0000000..ab7cd66 --- /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 19d9a12..f860b82 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 4e10bf3..4b165d6 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 5edefa0..367ba73 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 e108893..08e8d01 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 85bcb2b..28a895e 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 104b7ce..ba43ea3 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 e55301f..4864989 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 512a891..6fdd7e8 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 21371d8..945a38e 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 fe3a0eb..08d6a34 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 ae8b3a1..db80d98 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 -- cgit v1.1