aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/net/fd_unix.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/fd_unix.go')
-rw-r--r--libgo/go/net/fd_unix.go84
1 files changed, 18 insertions, 66 deletions
diff --git a/libgo/go/net/fd_unix.go b/libgo/go/net/fd_unix.go
index 95d5e4f..e7ab9a4 100644
--- a/libgo/go/net/fd_unix.go
+++ b/libgo/go/net/fd_unix.go
@@ -11,8 +11,8 @@ import (
"internal/poll"
"os"
"runtime"
- "sync/atomic"
"syscall"
+ "time"
)
// Network file descriptor.
@@ -22,7 +22,7 @@ type netFD struct {
// immutable until Close
family int
sotype int
- isConnected bool
+ isConnected bool // handshake completed or use of association with peer
net string
laddr Addr
raddr Addr
@@ -121,7 +121,7 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa sysc
// == nil). Because we've now poisoned the connection
// by making it unwritable, don't return a successful
// dial. This was issue 16523.
- ret = ctxErr
+ ret = mapErr(ctxErr)
fd.Close() // prevent a leak
}
}()
@@ -256,74 +256,26 @@ func (fd *netFD) accept() (netfd *netFD, err error) {
return netfd, nil
}
-// Use a helper function to call fcntl. This is defined in C in
-// libgo/runtime.
-//extern __go_fcntl_uintptr
-func fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
-
-// tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
-// If the kernel doesn't support it, this is set to 0.
-var tryDupCloexec = int32(1)
-
-func dupCloseOnExec(fd int) (newfd int, err error) {
- if atomic.LoadInt32(&tryDupCloexec) == 1 && syscall.F_DUPFD_CLOEXEC != 0 {
- syscall.Entersyscall()
- r0, errno := fcntl(uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
- syscall.Exitsyscall()
- e1 := syscall.Errno(errno)
- if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
- // On OS X 10.6 and below (but we only support
- // >= 10.6), F_DUPFD_CLOEXEC is unsupported
- // and fcntl there falls back (undocumented)
- // to doing an ioctl instead, returning EBADF
- // in this case because fd is not of the
- // expected device fd type. Treat it as
- // EINVAL instead, so we fall back to the
- // normal dup path.
- // TODO: only do this on 10.6 if we can detect 10.6
- // cheaply.
- e1 = syscall.EINVAL
- }
- switch e1 {
- case 0:
- return int(r0), nil
- case syscall.EINVAL:
- // Old kernel. Fall back to the portable way
- // from now on.
- atomic.StoreInt32(&tryDupCloexec, 0)
- default:
- return -1, os.NewSyscallError("fcntl", e1)
+func (fd *netFD) dup() (f *os.File, err error) {
+ ns, call, err := fd.pfd.Dup()
+ if err != nil {
+ if call != "" {
+ err = os.NewSyscallError(call, err)
}
+ return nil, err
}
- return dupCloseOnExecOld(fd)
-}
-// dupCloseOnExecUnixOld is the traditional way to dup an fd and
-// set its O_CLOEXEC bit, using two system calls.
-func dupCloseOnExecOld(fd int) (newfd int, err error) {
- syscall.ForkLock.RLock()
- defer syscall.ForkLock.RUnlock()
- newfd, err = syscall.Dup(fd)
- if err != nil {
- return -1, os.NewSyscallError("dup", err)
- }
- syscall.CloseOnExec(newfd)
- return
+ return os.NewFile(uintptr(ns), fd.name()), nil
}
-func (fd *netFD) dup() (f *os.File, err error) {
- ns, err := dupCloseOnExec(fd.pfd.Sysfd)
- if err != nil {
- return nil, err
- }
+func (fd *netFD) SetDeadline(t time.Time) error {
+ return fd.pfd.SetDeadline(t)
+}
- // We want blocking mode for the new fd, hence the double negative.
- // This also puts the old fd into blocking mode, meaning that
- // I/O will block the thread instead of letting us use the epoll server.
- // Everything will still work, just with more threads.
- if err = fd.pfd.SetBlocking(); err != nil {
- return nil, os.NewSyscallError("setnonblock", err)
- }
+func (fd *netFD) SetReadDeadline(t time.Time) error {
+ return fd.pfd.SetReadDeadline(t)
+}
- return os.NewFile(uintptr(ns), fd.name()), nil
+func (fd *netFD) SetWriteDeadline(t time.Time) error {
+ return fd.pfd.SetWriteDeadline(t)
}