]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: use dup3 in forkAndExecInChild1 if available
authorTobias Klauser <tklauser@distanz.ch>
Sun, 23 Feb 2020 17:14:34 +0000 (18:14 +0100)
committerTobias Klauser <tobias.klauser@gmail.com>
Mon, 24 Feb 2020 08:31:48 +0000 (08:31 +0000)
The dup3 syscall is available since Linux 2.6.27. Fall back to dup2 (if
available) if dup3 returns ENOSYS.

This allows to omit the additional fcntl call to mark the dup'ed fd as
close-on-exec.

Change-Id: If318b593edd783f2aa988534c6062498e7119ddb
Reviewed-on: https://go-review.googlesource.com/c/go/+/220422
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/syscall/exec_linux.go

index d639565b751d9f42e4bbcefe48a0c963a587c492..f32d68249388dce66817a300acbaed96467d68ac 100644 (file)
@@ -434,11 +434,16 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
        // 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 = RawSyscall(_SYS_dup, uintptr(pipe), uintptr(nextfd), 0)
-               if err1 != 0 {
+               _, _, err1 = RawSyscall(SYS_DUP3, uintptr(pipe), uintptr(nextfd), O_CLOEXEC)
+               if _SYS_dup != SYS_DUP3 && err1 == ENOSYS {
+                       _, _, err1 = RawSyscall(_SYS_dup, uintptr(pipe), uintptr(nextfd), 0)
+                       if err1 != 0 {
+                               goto childerror
+                       }
+                       RawSyscall(fcntl64Syscall, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+               } else if err1 != 0 {
                        goto childerror
                }
-               RawSyscall(fcntl64Syscall, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
                pipe = nextfd
                nextfd++
        }
@@ -447,11 +452,16 @@ func forkAndExecInChild1(argv0 *byte, argv, envv []*byte, chroot, dir *byte, att
                        if nextfd == pipe { // don't stomp on pipe
                                nextfd++
                        }
-                       _, _, err1 = RawSyscall(_SYS_dup, uintptr(fd[i]), uintptr(nextfd), 0)
-                       if err1 != 0 {
+                       _, _, err1 = RawSyscall(SYS_DUP3, uintptr(fd[i]), uintptr(nextfd), O_CLOEXEC)
+                       if _SYS_dup != SYS_DUP3 && err1 == ENOSYS {
+                               _, _, err1 = RawSyscall(_SYS_dup, uintptr(pipe), uintptr(nextfd), 0)
+                               if err1 != 0 {
+                                       goto childerror
+                               }
+                               RawSyscall(fcntl64Syscall, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
+                       } else if err1 != 0 {
                                goto childerror
                        }
-                       RawSyscall(fcntl64Syscall, uintptr(nextfd), F_SETFD, FD_CLOEXEC)
                        fd[i] = nextfd
                        nextfd++
                }