syscall: use fcntl F_DUP2FD_CLOEXEC in forkAndExecInChild on illumos
Use fcntl(oldfd, F_DUP2FD_CLOEXEC, newfd) to duplicate the file
descriptor and mark is as close-on-exec instead of dup2 & fcntl.
Illumos implements dup3 like this in libc.
Change-Id: I9782bce553ffb832e9b1a12bbf3c0a40c821f56e
Reviewed-on: https://go-review.googlesource.com/c/go/+/358374
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/src/syscall/exec_libc.go b/src/syscall/exec_libc.go
index 8a84954..b14abd4 100644
--- a/src/syscall/exec_libc.go
+++ b/src/syscall/exec_libc.go
@@ -10,6 +10,7 @@
package syscall
import (
+ "runtime"
"unsafe"
)
@@ -197,11 +198,19 @@
// Pass 1: look for fd[i] < i and move those up above len(fd)
// so that pass 2 won't stomp on an fd it needs later.
if pipe < nextfd {
- _, err1 = dup2child(uintptr(pipe), uintptr(nextfd))
+ switch runtime.GOOS {
+ case "illumos":
+ _, err1 = fcntl1(uintptr(pipe), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
+ default:
+ _, err1 = dup2child(uintptr(pipe), uintptr(nextfd))
+ if err1 != 0 {
+ goto childerror
+ }
+ _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+ }
if err1 != 0 {
goto childerror
}
- fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
pipe = nextfd
nextfd++
}
@@ -210,11 +219,16 @@
if nextfd == pipe { // don't stomp on pipe
nextfd++
}
- _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd))
- if err1 != 0 {
- goto childerror
+ switch runtime.GOOS {
+ case "illumos":
+ _, err1 = fcntl1(uintptr(fd[i]), _F_DUP2FD_CLOEXEC, uintptr(nextfd))
+ default:
+ _, err1 = dup2child(uintptr(fd[i]), uintptr(nextfd))
+ if err1 != 0 {
+ goto childerror
+ }
+ _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
}
- _, err1 = fcntl1(uintptr(nextfd), F_SETFD, FD_CLOEXEC)
if err1 != 0 {
goto childerror
}
diff --git a/src/syscall/syscall_aix.go b/src/syscall/syscall_aix.go
index 9c6afba..20e77ac 100644
--- a/src/syscall/syscall_aix.go
+++ b/src/syscall/syscall_aix.go
@@ -31,6 +31,8 @@
F_DUPFD_CLOEXEC = 0
// AF_LOCAL doesn't exist on AIX
AF_LOCAL = AF_UNIX
+
+ _F_DUP2FD_CLOEXEC = 0
)
func (ts *StTimespec_t) Unix() (sec int64, nsec int64) {
diff --git a/src/syscall/syscall_solaris.go b/src/syscall/syscall_solaris.go
index daa4b88..dedfbd0 100644
--- a/src/syscall/syscall_solaris.go
+++ b/src/syscall/syscall_solaris.go
@@ -14,6 +14,8 @@
import "unsafe"
+const _F_DUP2FD_CLOEXEC = F_DUP2FD_CLOEXEC
+
// Implemented in asm_solaris_amd64.s.
func rawSysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
func sysvicall6(trap, nargs, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)