I broke FreeBSD 9 in https://golang.org/cl/38426 by using Pipe2.
We still want to support FreeBSD 9 for one last release (Go 1.9 will
be the last), and FreeBSD 9 doesn't have Pipe2.
So this still uses Pipe2, but falls back to Pipe on error.
Updates #18854
Updates #19072
Change-Id: I1de90fb83606c93fb84b4b86fba31e207a702835
Reviewed-on: https://go-review.googlesource.com/38430
Reviewed-by: Rob Pike <r@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
e := syscall.Pipe2(p[0:], syscall.O_CLOEXEC)
if e != nil {
- return nil, nil, NewSyscallError("pipe", e)
+ // Fallback support for FreeBSD 9, which lacks Pipe2.
+ //
+ // TODO: remove this for Go 1.10 when FreeBSD 9
+ // is removed (Issue 19072).
+
+ // See ../syscall/exec.go for description of lock.
+ syscall.ForkLock.RLock()
+ e := syscall.Pipe(p[0:])
+ if e != nil {
+ syscall.ForkLock.RUnlock()
+ return nil, nil, NewSyscallError("pipe", e)
+ }
+ syscall.CloseOnExec(p[0])
+ syscall.CloseOnExec(p[1])
+ syscall.ForkLock.RUnlock()
}
return newFile(uintptr(p[0]), "|0", true), newFile(uintptr(p[1]), "|1", true), nil
package syscall
func forkExecPipe(p []int) error {
- return Pipe2(p, O_CLOEXEC)
+ err := Pipe2(p, O_CLOEXEC)
+ if err == nil {
+ return nil
+ }
+
+ // FreeBSD 9 fallback.
+ // TODO: remove this for Go 1.10 per Issue 19072
+ err = Pipe(p)
+ if err != nil {
+ return err
+ }
+ _, err = fcntl(p[0], F_SETFD, FD_CLOEXEC)
+ if err != nil {
+ return err
+ }
+ _, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
+ return err
}
return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
}
+//sysnb pipe() (r int, w int, err error)
+
func Pipe(p []int) error {
- return Pipe2(p, 0)
+ if len(p) != 2 {
+ return EINVAL
+ }
+ var err error
+ p[0], p[1], err = pipe()
+ return err
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func pipe() (r int, w int, err error) {
+ r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+ r = int(r0)
+ w = int(r1)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func pipe() (r int, w int, err error) {
+ r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+ r = int(r0)
+ w = int(r1)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func pipe() (r int, w int, err error) {
+ r0, r1, e1 := RawSyscall(SYS_PIPE, 0, 0, 0)
+ r = int(r0)
+ w = int(r1)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func pipe2(p *[2]_C_int, flags int) (err error) {
_, _, e1 := RawSyscall(SYS_PIPE2, uintptr(unsafe.Pointer(p)), uintptr(flags), 0)
if e1 != 0 {