]> Cypherpunks repositories - gostls13.git/commitdiff
os: use wait6 to avoid wait/kill race on freebsd
authorMikio Hara <mikioh.mikioh@gmail.com>
Sat, 11 Jun 2016 10:55:34 +0000 (19:55 +0900)
committerMikio Hara <mikioh.mikioh@gmail.com>
Mon, 13 Jun 2016 22:13:56 +0000 (22:13 +0000)
This change is a followup to https://go-review.googlesource.com/23967
for FreeBSD.

Updates #13987.
Updates #16028.

Change-Id: I0f0737372fce6df89d090fe9847305749b79eb4c
Reviewed-on: https://go-review.googlesource.com/24021
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/os/wait_unimp.go
src/os/wait_wait6.go [new file with mode: 0644]

index 254bf7ec177c7606a356f0a89de7b744920a53ec..7059e59ab240556c3e6b2f78a02c5ed66d3c4f4b 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build dragonfly freebsd nacl netbsd openbsd solaris
+// +build dragonfly nacl netbsd openbsd solaris
 
 package os
 
diff --git a/src/os/wait_wait6.go b/src/os/wait_wait6.go
new file mode 100644 (file)
index 0000000..279c6f2
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build freebsd
+
+package os
+
+import (
+       "runtime"
+       "syscall"
+)
+
+const _P_PID = 0
+
+// blockUntilWaitable attempts to block until a call to p.Wait will
+// succeed immediately, and returns whether it has done so.
+// It does not actually call p.Wait.
+func (p *Process) blockUntilWaitable() (bool, error) {
+       var errno syscall.Errno
+       switch runtime.GOARCH {
+       case "386", "arm":
+               // The arguments on 32-bit FreeBSD look like the
+               // following:
+               // - freebsd32_wait6_args{ idtype, id1, id2, status, options, wrusage, info } or
+               // - freebsd32_wait6_args{ idtype, pad, id1, id2, status, options, wrusage, info } when PAD64_REQUIRED=1 on MIPS or PowerPC
+               _, _, errno = syscall.Syscall9(syscall.SYS_WAIT6, _P_PID, 0, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0, 0, 0)
+       default:
+               _, _, errno = syscall.Syscall6(syscall.SYS_WAIT6, _P_PID, uintptr(p.Pid), 0, syscall.WEXITED|syscall.WNOWAIT, 0, 0)
+       }
+       if errno != 0 {
+               // The wait6 system call is supported only on FreeBSD
+               // 9.3 and above, so it may return an ENOSYS error.
+               // Also the system call may return an ECHILD error
+               // when the child process has not finished the
+               // transformation using execve system call.
+               // In both cases, we just leave the care of child
+               // process to the following wait4 system call in
+               // Process.wait.
+               if errno == syscall.ENOSYS || errno == syscall.ECHILD {
+                       return false, nil
+               }
+               return false, NewSyscallError("wait6", errno)
+       }
+       return true, nil
+}