diff --git a/src/os/file_plan9.go b/src/os/file_plan9.go index ef277deccce..c123fe69619 100644 --- a/src/os/file_plan9.go +++ b/src/os/file_plan9.go @@ -617,3 +617,7 @@ func newRawConn(file *File) (*rawConn, error) { func ignoringEINTR(fn func() error) error { return fn() } + +func ignoringEINTR2[T any](fn func() (T, error)) (T, error) { + return fn() +} diff --git a/src/os/file_posix.go b/src/os/file_posix.go index 8ff0ada4629..f0cdfdae5c9 100644 --- a/src/os/file_posix.go +++ b/src/os/file_posix.go @@ -254,3 +254,13 @@ func ignoringEINTR(fn func() error) error { } } } + +// ignoringEINTR2 is ignoringEINTR, but returning an additional value. +func ignoringEINTR2[T any](fn func() (T, error)) (T, error) { + for { + v, err := fn() + if err != syscall.EINTR { + return v, err + } + } +} diff --git a/src/os/file_unix.go b/src/os/file_unix.go index 73069faa567..b5c0baf3ab7 100644 --- a/src/os/file_unix.go +++ b/src/os/file_unix.go @@ -446,22 +446,15 @@ func Symlink(oldname, newname string) error { func readlink(name string) (string, error) { for len := 128; ; len *= 2 { b := make([]byte, len) - var ( - n int - e error - ) - for { - n, e = fixCount(syscall.Readlink(name, b)) - if e != syscall.EINTR { - break - } - } + n, err := ignoringEINTR2(func() (int, error) { + return fixCount(syscall.Readlink(name, b)) + }) // buffer too small - if (runtime.GOOS == "aix" || runtime.GOOS == "wasip1") && e == syscall.ERANGE { + if (runtime.GOOS == "aix" || runtime.GOOS == "wasip1") && err == syscall.ERANGE { continue } - if e != nil { - return "", &PathError{Op: "readlink", Path: name, Err: e} + if err != nil { + return "", &PathError{Op: "readlink", Path: name, Err: err} } if n < len { return string(b[0:n]), nil diff --git a/src/os/getwd.go b/src/os/getwd.go index 82f0d944df9..5ce948faf5d 100644 --- a/src/os/getwd.go +++ b/src/os/getwd.go @@ -53,12 +53,7 @@ func Getwd() (dir string, err error) { // If the operating system provides a Getwd call, use it. if syscall.ImplementsGetwd { - for { - dir, err = syscall.Getwd() - if err != syscall.EINTR { - break - } - } + dir, err = ignoringEINTR2(syscall.Getwd) // Linux returns ENAMETOOLONG if the result is too long. // Some BSD systems appear to return EINVAL. // FreeBSD systems appear to use ENOMEM diff --git a/src/os/removeall_at.go b/src/os/removeall_at.go index cc254e0043f..f52f6213f5f 100644 --- a/src/os/removeall_at.go +++ b/src/os/removeall_at.go @@ -166,20 +166,11 @@ func removeAllFrom(parent *File, base string) error { // we are going to (try to) remove the file. // The contents of this file are not relevant for test caching. func openDirAt(dirfd int, name string) (*File, error) { - var r int - for { - var e error - r, e = unix.Openat(dirfd, name, O_RDONLY|syscall.O_CLOEXEC|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0) - if e == nil { - break - } - - // See comment in openFileNolog. - if e == syscall.EINTR { - continue - } - - return nil, e + r, err := ignoringEINTR2(func() (int, error) { + return unix.Openat(dirfd, name, O_RDONLY|syscall.O_CLOEXEC|syscall.O_DIRECTORY|syscall.O_NOFOLLOW, 0) + }) + if err != nil { + return nil, err } if !supportsCloseOnExec {