diff --git a/Dockerfile b/Dockerfile index 1389a04..0518695 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,14 @@ RUN apk add glibc-2.23-r3.apk # Disable cgo so that binaries we build will be fully static. ENV CGO_ENABLED=0 +# Apply patches to Go runtime and recompile. +# See https://github.com/golang/go/issues/5838 for defails of vfork patch. +COPY patches/use-clone-vfork-b7edfba429d982e3e065d637334bcc63ad49f8f9.patch \ + /tmp/use-clone-vfork-b7edfba429d982e3e065d637334bcc63ad49f8f9.patch +RUN cd /usr/local/go && \ + patch -p 1 < /tmp/use-clone-vfork-b7edfba429d982e3e065d637334bcc63ad49f8f9.patch +RUN go install -v -a syscall + # Recompile the standard library with cgo disabled. This prevents the standard library from being # marked stale, causing full rebuilds every time. RUN go install -v std diff --git a/patches/use-clone-vfork-b7edfba429d982e3e065d637334bcc63ad49f8f9.patch b/patches/use-clone-vfork-b7edfba429d982e3e065d637334bcc63ad49f8f9.patch new file mode 100644 index 0000000..000fce4 --- /dev/null +++ b/patches/use-clone-vfork-b7edfba429d982e3e065d637334bcc63ad49f8f9.patch @@ -0,0 +1,76 @@ +From b7edfba429d982e3e065d637334bcc63ad49f8f9 Mon Sep 17 00:00:00 2001 +From: Richard Musiol +Date: Fri, 29 Apr 2016 19:22:36 +0200 +Subject: [PATCH] syscall: use CLONE_VFORK (WIP) + +--- + src/syscall/asm_linux_amd64.s | 25 +++++++++++++++++++++++++ + src/syscall/exec_linux.go | 7 +++++-- + src/syscall/syscall_linux_amd64.go | 2 ++ + 3 files changed, 32 insertions(+), 2 deletions(-) + +diff --git a/src/syscall/asm_linux_amd64.s b/src/syscall/asm_linux_amd64.s +index 6634875..a5255c1 100644 +--- a/src/syscall/asm_linux_amd64.s ++++ b/src/syscall/asm_linux_amd64.s +@@ -111,6 +111,31 @@ ok2: + MOVQ $0, err+72(FP) + RET + ++// func rawSyscall6PreserveRet(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) ++TEXT ·rawSyscall6PreserveRet(SB),NOSPLIT,$0-80 ++ MOVQ a1+8(FP), DI ++ MOVQ a2+16(FP), SI ++ MOVQ a3+24(FP), DX ++ MOVQ a4+32(FP), R10 ++ MOVQ a5+40(FP), R8 ++ MOVQ a6+48(FP), R9 ++ MOVQ trap+0(FP), AX // syscall entry ++ POPQ R12 // preserve return address ++ SYSCALL ++ PUSHQ R12 ++ CMPQ AX, $0xfffffffffffff001 ++ JLS ok2 ++ MOVQ $-1, r1+56(FP) ++ MOVQ $0, r2+64(FP) ++ NEGQ AX ++ MOVQ AX, err+72(FP) ++ RET ++ok2: ++ MOVQ AX, r1+56(FP) ++ MOVQ DX, r2+64(FP) ++ MOVQ $0, err+72(FP) ++ RET ++ + // func gettimeofday(tv *Timeval) (err uintptr) + TEXT ·gettimeofday(SB),NOSPLIT,$0-16 + MOVQ tv+0(FP), DI +diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go +index e49bad7..61a72ad 100644 +--- a/src/syscall/exec_linux.go ++++ b/src/syscall/exec_linux.go +@@ -94,9 +94,12 @@ func forkAndExecInChild(argv0 *byte, argv, envv []*byte, chroot, dir *byte, attr + // About to call fork. + // No more allocation or calls of non-assembly functions. + runtime_BeforeFork() +- if runtime.GOARCH == "s390x" { ++ switch { ++ case runtime.GOARCH == "amd64" && sys.Cloneflags&CLONE_NEWUSER == 0: ++ r1, _, err1 = rawSyscall6PreserveRet(SYS_CLONE, uintptr(SIGCHLD|CLONE_VFORK|CLONE_VM)|sys.Cloneflags, 0, 0, 0, 0, 0) ++ case runtime.GOARCH == "s390x": + r1, _, err1 = RawSyscall6(SYS_CLONE, 0, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0) +- } else { ++ default: + r1, _, err1 = RawSyscall6(SYS_CLONE, uintptr(SIGCHLD)|sys.Cloneflags, 0, 0, 0, 0, 0) + } + if err1 != 0 { +diff --git a/src/syscall/syscall_linux_amd64.go b/src/syscall/syscall_linux_amd64.go +index d1bda29..cf3e5d1 100644 +--- a/src/syscall/syscall_linux_amd64.go ++++ b/src/syscall/syscall_linux_amd64.go +@@ -144,3 +144,5 @@ func (msghdr *Msghdr) SetControllen(length int) { + func (cmsg *Cmsghdr) SetLen(length int) { + cmsg.Len = uint64(length) + } ++ ++func rawSyscall6PreserveRet(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)