diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-01-17 14:20:29 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-01-17 14:20:29 +0000 |
commit | c6d6367f848cfd8381aba41e035c5e7e873667c5 (patch) | |
tree | a218e98243463fc27f5053b4444e2544c63cd57a /libgo/go/os | |
parent | 9bff0086915f544fa648ea81131f035cb9ce79a4 (diff) | |
download | gcc-c6d6367f848cfd8381aba41e035c5e7e873667c5.zip gcc-c6d6367f848cfd8381aba41e035c5e7e873667c5.tar.gz gcc-c6d6367f848cfd8381aba41e035c5e7e873667c5.tar.bz2 |
libgo: update to Go1.10beta2 release
Reviewed-on: https://go-review.googlesource.com/87897
From-SVN: r256794
Diffstat (limited to 'libgo/go/os')
-rw-r--r-- | libgo/go/os/env.go | 7 | ||||
-rw-r--r-- | libgo/go/os/exec.go | 5 | ||||
-rw-r--r-- | libgo/go/os/exec/exec_test.go | 13 | ||||
-rw-r--r-- | libgo/go/os/executable_test.go | 2 | ||||
-rw-r--r-- | libgo/go/os/file.go | 21 | ||||
-rw-r--r-- | libgo/go/os/file_plan9.go | 8 | ||||
-rw-r--r-- | libgo/go/os/file_unix.go | 10 | ||||
-rw-r--r-- | libgo/go/os/getwd.go | 12 | ||||
-rw-r--r-- | libgo/go/os/os_test.go | 20 | ||||
-rw-r--r-- | libgo/go/os/path.go | 2 | ||||
-rw-r--r-- | libgo/go/os/pipe_test.go | 85 | ||||
-rw-r--r-- | libgo/go/os/stat.go | 69 | ||||
-rw-r--r-- | libgo/go/os/stat_plan9.go | 14 | ||||
-rw-r--r-- | libgo/go/os/stat_unix.go | 12 |
14 files changed, 178 insertions, 102 deletions
diff --git a/libgo/go/os/env.go b/libgo/go/os/env.go index a03b8f6..4e0171f 100644 --- a/libgo/go/os/env.go +++ b/libgo/go/os/env.go @@ -6,7 +6,10 @@ package os -import "syscall" +import ( + "internal/testlog" + "syscall" +) // Expand replaces ${var} or $var in the string based on the mapping function. // For example, os.ExpandEnv(s) is equivalent to os.Expand(s, os.Getenv). @@ -78,6 +81,7 @@ func getShellName(s string) (string, int) { // It returns the value, which will be empty if the variable is not present. // To distinguish between an empty value and an unset value, use LookupEnv. func Getenv(key string) string { + testlog.Getenv(key) v, _ := syscall.Getenv(key) return v } @@ -88,6 +92,7 @@ func Getenv(key string) string { // Otherwise the returned value will be empty and the boolean will // be false. func LookupEnv(key string) (string, bool) { + testlog.Getenv(key) return syscall.Getenv(key) } diff --git a/libgo/go/os/exec.go b/libgo/go/os/exec.go index 8a53e5d..b3f60b6 100644 --- a/libgo/go/os/exec.go +++ b/libgo/go/os/exec.go @@ -5,6 +5,7 @@ package os import ( + "internal/testlog" "runtime" "sync" "sync/atomic" @@ -84,13 +85,15 @@ func FindProcess(pid int) (*Process, error) { } // StartProcess starts a new process with the program, arguments and attributes -// specified by name, argv and attr. +// specified by name, argv and attr. The argv slice will become os.Args in the +// new process, so it normally starts with the program name. // // StartProcess is a low-level interface. The os/exec package provides // higher-level interfaces. // // If there is an error, it will be of type *PathError. func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) { + testlog.Open(name) return startProcess(name, argv, attr) } diff --git a/libgo/go/os/exec/exec_test.go b/libgo/go/os/exec/exec_test.go index a877d8a..aa33570f 100644 --- a/libgo/go/os/exec/exec_test.go +++ b/libgo/go/os/exec/exec_test.go @@ -405,9 +405,15 @@ var testedAlreadyLeaked = false // basefds returns the number of expected file descriptors // to be present in a process at start. -// stdin, stdout, stderr, epoll/kqueue +// stdin, stdout, stderr, epoll/kqueue, maybe testlog func basefds() uintptr { - return os.Stderr.Fd() + 1 + n := os.Stderr.Fd() + 1 + for _, arg := range os.Args { + if strings.HasPrefix(arg, "-test.testlogfile=") { + n++ + } + } + return n } func closeUnexpectedFds(t *testing.T, m string) { @@ -1003,6 +1009,9 @@ func TestContext(t *testing.T) { } func TestContextCancel(t *testing.T) { + if testenv.Builder() == "windows-386-xp" { + t.Skipf("known to fail on Windows XP. Issue 17245") + } ctx, cancel := context.WithCancel(context.Background()) defer cancel() c := helperCommandContext(t, ctx, "cat") diff --git a/libgo/go/os/executable_test.go b/libgo/go/os/executable_test.go index 7800844..4a9a883 100644 --- a/libgo/go/os/executable_test.go +++ b/libgo/go/os/executable_test.go @@ -17,7 +17,7 @@ import ( const executable_EnvVar = "OSTEST_OUTPUT_EXECPATH" func TestExecutable(t *testing.T) { - testenv.MustHaveExec(t) // will also execlude nacl, which doesn't support Executable anyway + testenv.MustHaveExec(t) // will also exclude nacl, which doesn't support Executable anyway ep, err := os.Executable() if err != nil { t.Fatalf("Executable failed: %v", err) diff --git a/libgo/go/os/file.go b/libgo/go/os/file.go index 542b074..c667421 100644 --- a/libgo/go/os/file.go +++ b/libgo/go/os/file.go @@ -39,6 +39,7 @@ package os import ( "errors" "internal/poll" + "internal/testlog" "io" "syscall" "time" @@ -207,7 +208,8 @@ func (f *File) WriteString(s string) (n int, err error) { return f.Write([]byte(s)) } -// Mkdir creates a new directory with the specified name and permission bits. +// Mkdir creates a new directory with the specified name and permission +// bits (before umask). // If there is an error, it will be of type *PathError. func Mkdir(name string, perm FileMode) error { e := syscall.Mkdir(fixLongPath(name), syscallMode(perm)) @@ -228,8 +230,15 @@ func Mkdir(name string, perm FileMode) error { // If there is an error, it will be of type *PathError. func Chdir(dir string) error { if e := syscall.Chdir(dir); e != nil { + testlog.Open(dir) // observe likely non-existent directory return &PathError{"chdir", dir, e} } + if log := testlog.Logger(); log != nil { + wd, err := Getwd() + if err == nil { + log.Chdir(wd) + } + } return nil } @@ -250,6 +259,16 @@ func Create(name string) (*File, error) { return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666) } +// OpenFile is the generalized open call; most users will use Open +// or Create instead. It opens the named file with specified flag +// (O_RDONLY etc.) and perm (before umask), if applicable. If successful, +// methods on the returned File can be used for I/O. +// If there is an error, it will be of type *PathError. +func OpenFile(name string, flag int, perm FileMode) (*File, error) { + testlog.Open(name) + return openFileNolog(name, flag, perm) +} + // lstat is overridden in tests. var lstat = Lstat diff --git a/libgo/go/os/file_plan9.go b/libgo/go/os/file_plan9.go index e4f8fd9..7e28178 100644 --- a/libgo/go/os/file_plan9.go +++ b/libgo/go/os/file_plan9.go @@ -79,12 +79,8 @@ func syscallMode(i FileMode) (o uint32) { return } -// OpenFile is the generalized open call; most users will use Open -// or Create instead. It opens the named file with specified flag -// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, -// methods on the returned File can be used for I/O. -// If there is an error, it will be of type *PathError. -func OpenFile(name string, flag int, perm FileMode) (*File, error) { +// openFileNolog is the Plan 9 implementation of OpenFile. +func openFileNolog(name string, flag int, perm FileMode) (*File, error) { var ( fd int e error diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go index af9c37f9..67d2ee1 100644 --- a/libgo/go/os/file_unix.go +++ b/libgo/go/os/file_unix.go @@ -66,7 +66,7 @@ func (f *File) Fd() uintptr { // opened in blocking mode. The File will continue to work, // but any blocking operation will tie up a thread. if f.nonblock { - syscall.SetNonblock(f.pfd.Sysfd, false) + f.pfd.SetBlocking() } return uintptr(f.pfd.Sysfd) @@ -152,12 +152,8 @@ func epipecheck(file *File, e error) { // On Unix-like systems, it is "/dev/null"; on Windows, "NUL". const DevNull = "/dev/null" -// OpenFile is the generalized open call; most users will use Open -// or Create instead. It opens the named file with specified flag -// (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, -// methods on the returned File can be used for I/O. -// If there is an error, it will be of type *PathError. -func OpenFile(name string, flag int, perm FileMode) (*File, error) { +// openFileNolog is the Unix implementation of OpenFile. +func openFileNolog(name string, flag int, perm FileMode) (*File, error) { chmod := false if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 { if _, err := Stat(name); IsNotExist(err) { diff --git a/libgo/go/os/getwd.go b/libgo/go/os/getwd.go index 4c3c0d9..87ad8eb 100644 --- a/libgo/go/os/getwd.go +++ b/libgo/go/os/getwd.go @@ -30,13 +30,13 @@ func Getwd() (dir string, err error) { // Clumsy but widespread kludge: // if $PWD is set and matches ".", use it. - dot, err := Stat(".") + dot, err := statNolog(".") if err != nil { return "", err } dir = Getenv("PWD") if len(dir) > 0 && dir[0] == '/' { - d, err := Stat(dir) + d, err := statNolog(dir) if err == nil && SameFile(dot, d) { return dir, nil } @@ -56,7 +56,7 @@ func Getwd() (dir string, err error) { dir = getwdCache.dir getwdCache.Unlock() if len(dir) > 0 { - d, err := Stat(dir) + d, err := statNolog(dir) if err == nil && SameFile(dot, d) { return dir, nil } @@ -64,7 +64,7 @@ func Getwd() (dir string, err error) { // Root is a special case because it has no parent // and ends in a slash. - root, err := Stat("/") + root, err := statNolog("/") if err != nil { // Can't stat root - no hope. return "", err @@ -81,7 +81,7 @@ func Getwd() (dir string, err error) { if len(parent) >= 1024 { // Sanity check return "", syscall.ENAMETOOLONG } - fd, err := Open(parent) + fd, err := openFileNolog(parent, O_RDONLY, 0) if err != nil { return "", err } @@ -93,7 +93,7 @@ func Getwd() (dir string, err error) { return "", err } for _, name := range names { - d, _ := Lstat(parent + "/" + name) + d, _ := lstatNolog(parent + "/" + name) if SameFile(d, dot) { dir = "/" + name + dir goto Found diff --git a/libgo/go/os/os_test.go b/libgo/go/os/os_test.go index e1c5b45..8ed9252 100644 --- a/libgo/go/os/os_test.go +++ b/libgo/go/os/os_test.go @@ -1360,14 +1360,26 @@ func TestSeek(t *testing.T) { {-1, io.SeekEnd, int64(len(data)) - 1}, {1 << 33, io.SeekStart, 1 << 33}, {1 << 33, io.SeekEnd, 1<<33 + int64(len(data))}, + + // Issue 21681, Windows 4G-1, etc: + {1<<32 - 1, io.SeekStart, 1<<32 - 1}, + {0, io.SeekCurrent, 1<<32 - 1}, + {2<<32 - 1, io.SeekStart, 2<<32 - 1}, + {0, io.SeekCurrent, 2<<32 - 1}, } for i, tt := range tests { + if runtime.GOOS == "nacl" && tt.out > 1<<30 { + t.Logf("skipping test case #%d on nacl; https://golang.org/issue/21728", i) + continue + } off, err := f.Seek(tt.in, tt.whence) if off != tt.out || err != nil { - if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 { - // Reiserfs rejects the big seeks. - // https://golang.org/issue/91 - break + if e, ok := err.(*PathError); ok && e.Err == syscall.EINVAL && tt.out > 1<<32 && runtime.GOOS == "linux" { + mounts, _ := ioutil.ReadFile("/proc/mounts") + if strings.Contains(string(mounts), "reiserfs") { + // Reiserfs rejects the big seeks. + t.Skipf("skipping test known to fail on reiserfs; https://golang.org/issue/91") + } } t.Errorf("#%d: Seek(%v, %v) = %v, %v want %v, nil", i, tt.in, tt.whence, off, err, tt.out) } diff --git a/libgo/go/os/path.go b/libgo/go/os/path.go index 17c49c8..eb996e5 100644 --- a/libgo/go/os/path.go +++ b/libgo/go/os/path.go @@ -13,7 +13,7 @@ import ( // MkdirAll creates a directory named path, // along with any necessary parents, and returns nil, // or else returns an error. -// The permission bits perm are used for all +// The permission bits perm (before umask) are used for all // directories that MkdirAll creates. // If path is already a directory, MkdirAll does nothing // and returns nil. diff --git a/libgo/go/os/pipe_test.go b/libgo/go/os/pipe_test.go index 9d79d84..aad6c27 100644 --- a/libgo/go/os/pipe_test.go +++ b/libgo/go/os/pipe_test.go @@ -10,6 +10,7 @@ package os_test import ( "fmt" "internal/testenv" + "io" "io/ioutil" "os" osexec "os/exec" @@ -17,6 +18,7 @@ import ( "runtime" "strconv" "strings" + "sync" "syscall" "testing" "time" @@ -220,3 +222,86 @@ func TestReadNonblockingFd(t *testing.T) { t.Errorf("child process failed: %v", err) } } + +func TestCloseWithBlockingReadByNewFile(t *testing.T) { + var p [2]int + err := syscall.Pipe(p[:]) + if err != nil { + t.Fatal(err) + } + // os.NewFile returns a blocking mode file. + testCloseWithBlockingRead(t, os.NewFile(uintptr(p[0]), "reader"), os.NewFile(uintptr(p[1]), "writer")) +} + +func TestCloseWithBlockingReadByFd(t *testing.T) { + r, w, err := os.Pipe() + if err != nil { + t.Fatal(err) + } + // Calling Fd will put the file into blocking mode. + _ = r.Fd() + testCloseWithBlockingRead(t, r, w) +} + +// Test that we don't let a blocking read prevent a close. +func testCloseWithBlockingRead(t *testing.T, r, w *os.File) { + defer r.Close() + defer w.Close() + + c1, c2 := make(chan bool), make(chan bool) + var wg sync.WaitGroup + + wg.Add(1) + go func(c chan bool) { + defer wg.Done() + // Give the other goroutine a chance to enter the Read + // or Write call. This is sloppy but the test will + // pass even if we close before the read/write. + time.Sleep(20 * time.Millisecond) + + if err := r.Close(); err != nil { + t.Error(err) + } + close(c) + }(c1) + + wg.Add(1) + go func(c chan bool) { + defer wg.Done() + var b [1]byte + _, err := r.Read(b[:]) + close(c) + if err == nil { + t.Error("I/O on closed pipe unexpectedly succeeded") + } + if err != io.EOF { + t.Errorf("got %v, expected io.EOF", err) + } + }(c2) + + for c1 != nil || c2 != nil { + select { + case <-c1: + c1 = nil + // r.Close has completed, but the blocking Read + // is hanging. Close the writer to unblock it. + w.Close() + case <-c2: + c2 = nil + case <-time.After(1 * time.Second): + switch { + case c1 != nil && c2 != nil: + t.Error("timed out waiting for Read and Close") + w.Close() + case c1 != nil: + t.Error("timed out waiting for Close") + case c2 != nil: + t.Error("timed out waiting for Read") + default: + t.Error("impossible case") + } + } + } + + wg.Wait() +} diff --git a/libgo/go/os/stat.go b/libgo/go/os/stat.go index 564215b..af66838 100644 --- a/libgo/go/os/stat.go +++ b/libgo/go/os/stat.go @@ -1,64 +1,23 @@ -// Copyright 2009 The Go Authors. All rights reserved. +// 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. -// +build !aix -// +build !darwin -// +build !freebsd -// +build !linux -// +build !netbsd -// +build !openbsd -// +build !solaris - package os -import ( - "syscall" - "time" -) - -func sameFile(fs1, fs2 *fileStat) bool { - stat1 := fs1.sys.(*syscall.Stat_t) - stat2 := fs2.sys.(*syscall.Stat_t) - return stat1.Dev == stat2.Dev && stat1.Ino == stat2.Ino -} - -func fileInfoFromStat(st *syscall.Stat_t, name string) FileInfo { - fs := &fileStat{ - name: basename(name), - size: int64(st.Size), - modTime: timespecToTime(st.Mtim), - sys: st, - } - fs.mode = FileMode(st.Mode & 0777) - switch st.Mode & syscall.S_IFMT { - case syscall.S_IFBLK, syscall.S_IFCHR: - fs.mode |= ModeDevice - case syscall.S_IFDIR: - fs.mode |= ModeDir - case syscall.S_IFIFO: - fs.mode |= ModeNamedPipe - case syscall.S_IFLNK: - fs.mode |= ModeSymlink - case syscall.S_IFREG: - // nothing to do - case syscall.S_IFSOCK: - fs.mode |= ModeSocket - } - if st.Mode&syscall.S_ISGID != 0 { - fs.mode |= ModeSetgid - } - if st.Mode&syscall.S_ISUID != 0 { - fs.mode |= ModeSetuid - } - return fs -} +import "internal/testlog" -func timespecToTime(ts syscall.Timespec) time.Time { - return time.Unix(int64(ts.Sec), int64(ts.Nsec)) +// Stat returns a FileInfo describing the named file. +// If there is an error, it will be of type *PathError. +func Stat(name string) (FileInfo, error) { + testlog.Stat(name) + return statNolog(name) } -// For testing. -func atime(fi FileInfo) time.Time { - return timespecToTime(fi.Sys().(*syscall.Stat_t).Atim) +// Lstat returns a FileInfo describing the named file. +// If the file is a symbolic link, the returned FileInfo +// describes the symbolic link. Lstat makes no attempt to follow the link. +// If there is an error, it will be of type *PathError. +func Lstat(name string) (FileInfo, error) { + testlog.Stat(name) + return lstatNolog(name) } diff --git a/libgo/go/os/stat_plan9.go b/libgo/go/os/stat_plan9.go index 274d0d8..8057fd4 100644 --- a/libgo/go/os/stat_plan9.go +++ b/libgo/go/os/stat_plan9.go @@ -86,9 +86,8 @@ func dirstat(arg interface{}) (*syscall.Dir, error) { return nil, &PathError{"stat", name, err} } -// Stat returns a FileInfo describing the named file. -// If there is an error, it will be of type *PathError. -func Stat(name string) (FileInfo, error) { +// statNolog implements Stat for Plan 9. +func statNolog(name string) (FileInfo, error) { d, err := dirstat(name) if err != nil { return nil, err @@ -96,12 +95,9 @@ func Stat(name string) (FileInfo, error) { return fileInfoFromStat(d), nil } -// Lstat returns a FileInfo describing the named file. -// If the file is a symbolic link, the returned FileInfo -// describes the symbolic link. Lstat makes no attempt to follow the link. -// If there is an error, it will be of type *PathError. -func Lstat(name string) (FileInfo, error) { - return Stat(name) +// lstatNolog implements Lstat for Plan 9. +func lstatNolog(name string) (FileInfo, error) { + return statNolog(name) } // For testing. diff --git a/libgo/go/os/stat_unix.go b/libgo/go/os/stat_unix.go index 7855fba..bc5d06c 100644 --- a/libgo/go/os/stat_unix.go +++ b/libgo/go/os/stat_unix.go @@ -25,9 +25,8 @@ func (f *File) Stat() (FileInfo, error) { return &fs, nil } -// Stat returns a FileInfo describing the named file. -// If there is an error, it will be of type *PathError. -func Stat(name string) (FileInfo, error) { +// statNolog stats a file with no test logging. +func statNolog(name string) (FileInfo, error) { var fs fileStat err := syscall.Stat(name, &fs.sys) if err != nil { @@ -37,11 +36,8 @@ func Stat(name string) (FileInfo, error) { return &fs, nil } -// Lstat returns a FileInfo describing the named file. -// If the file is a symbolic link, the returned FileInfo -// describes the symbolic link. Lstat makes no attempt to follow the link. -// If there is an error, it will be of type *PathError. -func Lstat(name string) (FileInfo, error) { +// lstatNolog lstats a file with no test logging. +func lstatNolog(name string) (FileInfo, error) { var fs fileStat err := syscall.Lstat(name, &fs.sys) if err != nil { |