diff options
author | Ian Lance Taylor <iant@golang.org> | 2017-09-14 17:11:35 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-09-14 17:11:35 +0000 |
commit | bc998d034f45d1828a8663b2eed928faf22a7d01 (patch) | |
tree | 8d262a22ca7318f4bcd64269fe8fe9e45bcf8d0f /libgo/go/net/fd_unix.go | |
parent | a41a6142df74219f596e612d3a7775f68ca6e96f (diff) | |
download | gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.zip gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.gz gcc-bc998d034f45d1828a8663b2eed928faf22a7d01.tar.bz2 |
libgo: update to go1.9
Reviewed-on: https://go-review.googlesource.com/63753
From-SVN: r252767
Diffstat (limited to 'libgo/go/net/fd_unix.go')
-rw-r--r-- | libgo/go/net/fd_unix.go | 351 |
1 files changed, 76 insertions, 275 deletions
diff --git a/libgo/go/net/fd_unix.go b/libgo/go/net/fd_unix.go index b6ee059..e5afd1a 100644 --- a/libgo/go/net/fd_unix.go +++ b/libgo/go/net/fd_unix.go @@ -8,7 +8,7 @@ package net import ( "context" - "io" + "internal/poll" "os" "runtime" "sync/atomic" @@ -17,38 +17,33 @@ import ( // Network file descriptor. type netFD struct { - // locking/lifetime of sysfd + serialize access to Read and Write methods - fdmu fdMutex + pfd poll.FD // immutable until Close - sysfd int family int sotype int - isStream bool isConnected bool net string laddr Addr raddr Addr - - // writev cache. - iovecs *[]syscall.Iovec - - // wait server - pd pollDesc -} - -func sysInit() { } func newFD(sysfd, family, sotype int, net string) (*netFD, error) { - return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net, isStream: sotype == syscall.SOCK_STREAM}, nil + ret := &netFD{ + pfd: poll.FD{ + Sysfd: sysfd, + IsStream: sotype == syscall.SOCK_STREAM, + ZeroReadIsEOF: sotype != syscall.SOCK_DGRAM && sotype != syscall.SOCK_RAW, + }, + family: family, + sotype: sotype, + net: net, + } + return ret, nil } func (fd *netFD) init() error { - if err := fd.pd.init(fd); err != nil { - return err - } - return nil + return fd.pfd.Init(fd.net, true) } func (fd *netFD) setAddr(laddr, raddr Addr) { @@ -68,22 +63,23 @@ func (fd *netFD) name() string { return fd.net + ":" + ls + "->" + rs } -func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret error) { +func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (rsa syscall.Sockaddr, ret error) { // Do not need to call fd.writeLock here, // because fd is not yet accessible to user, // so no concurrent operations are possible. - switch err := connectFunc(fd.sysfd, ra); err { + switch err := connectFunc(fd.pfd.Sysfd, ra); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: case nil, syscall.EISCONN: select { case <-ctx.Done(): - return mapErr(ctx.Err()) + return nil, mapErr(ctx.Err()) default: } - if err := fd.init(); err != nil { - return err + if err := fd.pfd.Init(fd.net, true); err != nil { + return nil, err } - return nil + runtime.KeepAlive(fd) + return nil, nil case syscall.EINVAL: // On Solaris we can see EINVAL if the socket has // already been accepted and closed by the server. @@ -91,18 +87,18 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret erro // the socket will see EOF. For details and a test // case in C see https://golang.org/issue/6828. if runtime.GOOS == "solaris" { - return nil + return nil, nil } fallthrough default: - return os.NewSyscallError("connect", err) + return nil, os.NewSyscallError("connect", err) } - if err := fd.init(); err != nil { - return err + if err := fd.pfd.Init(fd.net, true); err != nil { + return nil, err } if deadline, _ := ctx.Deadline(); !deadline.IsZero() { - fd.setWriteDeadline(deadline) - defer fd.setWriteDeadline(noDeadline) + fd.pfd.SetWriteDeadline(deadline) + defer fd.pfd.SetWriteDeadline(noDeadline) } // Start the "interrupter" goroutine, if this context might be canceled. @@ -119,7 +115,7 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret erro defer func() { close(done) if ctxErr := <-interruptRes; ctxErr != nil && ret == nil { - // The interrupter goroutine called setWriteDeadline, + // The interrupter goroutine called SetWriteDeadline, // but the connect code below had returned from // waitWrite already and did a successful connect (ret // == nil). Because we've now poisoned the connection @@ -135,7 +131,7 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret erro // Force the runtime's poller to immediately give up // waiting for writability, unblocking waitWrite // below. - fd.setWriteDeadline(aLongTimeAgo) + fd.pfd.SetWriteDeadline(aLongTimeAgo) testHookCanceledDial() interruptRes <- ctx.Err() case <-done: @@ -153,66 +149,45 @@ func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret erro // SO_ERROR socket option to see if the connection // succeeded or failed. See issue 7474 for further // details. - if err := fd.pd.waitWrite(); err != nil { + if err := fd.pfd.WaitWrite(); err != nil { select { case <-ctx.Done(): - return mapErr(ctx.Err()) + return nil, mapErr(ctx.Err()) default: } - return err + return nil, err } - nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) + nerr, err := getsockoptIntFunc(fd.pfd.Sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) if err != nil { - return os.NewSyscallError("getsockopt", err) + return nil, os.NewSyscallError("getsockopt", err) } switch err := syscall.Errno(nerr); err { case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: - case syscall.Errno(0), syscall.EISCONN: - if runtime.GOOS != "darwin" { - return nil - } - // See golang.org/issue/14548. - // On Darwin, multiple connect system calls on - // a non-blocking socket never harm SO_ERROR. - switch err := connectFunc(fd.sysfd, ra); err { - case nil, syscall.EISCONN: - return nil + case syscall.EISCONN: + return nil, nil + case syscall.Errno(0): + // The runtime poller can wake us up spuriously; + // see issues 14548 and 19289. Check that we are + // really connected; if not, wait again. + if rsa, err := syscall.Getpeername(fd.pfd.Sysfd); err == nil { + return rsa, nil } default: - return os.NewSyscallError("getsockopt", err) + return nil, os.NewSyscallError("getsockopt", err) } + runtime.KeepAlive(fd) } } -func (fd *netFD) destroy() { - // Poller may want to unregister fd in readiness notification mechanism, - // so this must be executed before closeFunc. - fd.pd.close() - closeFunc(fd.sysfd) - fd.sysfd = -1 - runtime.SetFinalizer(fd, nil) -} - func (fd *netFD) Close() error { - if !fd.fdmu.increfAndClose() { - return errClosing - } - // Unblock any I/O. Once it all unblocks and returns, - // so that it cannot be referring to fd.sysfd anymore, - // the final decref will close fd.sysfd. This should happen - // fairly quickly, since all the I/O is non-blocking, and any - // attempts to block in the pollDesc will return errClosing. - fd.pd.evict() - fd.decref() - return nil + runtime.SetFinalizer(fd, nil) + return fd.pfd.Close() } func (fd *netFD) shutdown(how int) error { - if err := fd.incref(); err != nil { - return err - } - defer fd.decref() - return os.NewSyscallError("shutdown", syscall.Shutdown(fd.sysfd, how)) + err := fd.pfd.Shutdown(how) + runtime.KeepAlive(fd) + return wrapSyscallError("shutdown", err) } func (fd *netFD) closeRead() error { @@ -224,233 +199,59 @@ func (fd *netFD) closeWrite() error { } func (fd *netFD) Read(p []byte) (n int, err error) { - if err := fd.readLock(); err != nil { - return 0, err - } - defer fd.readUnlock() - if len(p) == 0 { - // If the caller wanted a zero byte read, return immediately - // without trying. (But after acquiring the readLock.) Otherwise - // syscall.Read returns 0, nil and eofError turns that into - // io.EOF. - // TODO(bradfitz): make it wait for readability? (Issue 15735) - return 0, nil - } - if err := fd.pd.prepareRead(); err != nil { - return 0, err - } - if fd.isStream && len(p) > 1<<30 { - p = p[:1<<30] - } - for { - n, err = syscall.Read(fd.sysfd, p) - if err != nil { - n = 0 - if err == syscall.EAGAIN { - if err = fd.pd.waitRead(); err == nil { - continue - } - } - } - err = fd.eofError(n, err) - break - } - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("read", err) - } - return + n, err = fd.pfd.Read(p) + runtime.KeepAlive(fd) + return n, wrapSyscallError("read", err) } func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { - if err := fd.readLock(); err != nil { - return 0, nil, err - } - defer fd.readUnlock() - if err := fd.pd.prepareRead(); err != nil { - return 0, nil, err - } - for { - n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) - if err != nil { - n = 0 - if err == syscall.EAGAIN { - if err = fd.pd.waitRead(); err == nil { - continue - } - } - } - err = fd.eofError(n, err) - break - } - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("recvfrom", err) - } - return + n, sa, err = fd.pfd.ReadFrom(p) + runtime.KeepAlive(fd) + return n, sa, wrapSyscallError("recvfrom", err) } func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { - if err := fd.readLock(); err != nil { - return 0, 0, 0, nil, err - } - defer fd.readUnlock() - if err := fd.pd.prepareRead(); err != nil { - return 0, 0, 0, nil, err - } - for { - n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) - if err != nil { - // TODO(dfc) should n and oobn be set to 0 - if err == syscall.EAGAIN { - if err = fd.pd.waitRead(); err == nil { - continue - } - } - } - err = fd.eofError(n, err) - break - } - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("recvmsg", err) - } - return + n, oobn, flags, sa, err = fd.pfd.ReadMsg(p, oob) + runtime.KeepAlive(fd) + return n, oobn, flags, sa, wrapSyscallError("recvmsg", err) } func (fd *netFD) Write(p []byte) (nn int, err error) { - if err := fd.writeLock(); err != nil { - return 0, err - } - defer fd.writeUnlock() - if err := fd.pd.prepareWrite(); err != nil { - return 0, err - } - for { - var n int - max := len(p) - if fd.isStream && max-nn > 1<<30 { - max = nn + 1<<30 - } - n, err = syscall.Write(fd.sysfd, p[nn:max]) - if n > 0 { - nn += n - } - if nn == len(p) { - break - } - if err == syscall.EAGAIN { - if err = fd.pd.waitWrite(); err == nil { - continue - } - } - if err != nil { - break - } - if n == 0 { - err = io.ErrUnexpectedEOF - break - } - } - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("write", err) - } - return nn, err + nn, err = fd.pfd.Write(p) + runtime.KeepAlive(fd) + return nn, wrapSyscallError("write", err) } func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { - if err := fd.writeLock(); err != nil { - return 0, err - } - defer fd.writeUnlock() - if err := fd.pd.prepareWrite(); err != nil { - return 0, err - } - for { - err = syscall.Sendto(fd.sysfd, p, 0, sa) - if err == syscall.EAGAIN { - if err = fd.pd.waitWrite(); err == nil { - continue - } - } - break - } - if err == nil { - n = len(p) - } - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("sendto", err) - } - return + n, err = fd.pfd.WriteTo(p, sa) + runtime.KeepAlive(fd) + return n, wrapSyscallError("sendto", err) } func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { - if err := fd.writeLock(); err != nil { - return 0, 0, err - } - defer fd.writeUnlock() - if err := fd.pd.prepareWrite(); err != nil { - return 0, 0, err - } - for { - n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) - if err == syscall.EAGAIN { - if err = fd.pd.waitWrite(); err == nil { - continue - } - } - break - } - if err == nil { - oobn = len(oob) - } - if _, ok := err.(syscall.Errno); ok { - err = os.NewSyscallError("sendmsg", err) - } - return + n, oobn, err = fd.pfd.WriteMsg(p, oob, sa) + runtime.KeepAlive(fd) + return n, oobn, wrapSyscallError("sendmsg", err) } func (fd *netFD) accept() (netfd *netFD, err error) { - if err := fd.readLock(); err != nil { - return nil, err - } - defer fd.readUnlock() - - var s int - var rsa syscall.Sockaddr - if err = fd.pd.prepareRead(); err != nil { - return nil, err - } - for { - s, rsa, err = accept(fd.sysfd) - if err != nil { - nerr, ok := err.(*os.SyscallError) - if !ok { - return nil, err - } - switch nerr.Err { - case syscall.EAGAIN: - if err = fd.pd.waitRead(); err == nil { - continue - } - case syscall.ECONNABORTED: - // This means that a socket on the - // listen queue was closed before we - // Accept()ed it; it's a silly error, - // so try again. - continue - } - return nil, err + d, rsa, errcall, err := fd.pfd.Accept() + if err != nil { + if errcall != "" { + err = wrapSyscallError(errcall, err) } - break + return nil, err } - if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { - closeFunc(s) + if netfd, err = newFD(d, fd.family, fd.sotype, fd.net); err != nil { + poll.CloseFunc(d) return nil, err } if err = netfd.init(); err != nil { fd.Close() return nil, err } - lsa, _ := syscall.Getsockname(netfd.sysfd) + lsa, _ := syscall.Getsockname(netfd.pfd.Sysfd) netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) return netfd, nil } @@ -511,7 +312,7 @@ func dupCloseOnExecOld(fd int) (newfd int, err error) { } func (fd *netFD) dup() (f *os.File, err error) { - ns, err := dupCloseOnExec(fd.sysfd) + ns, err := dupCloseOnExec(fd.pfd.Sysfd) if err != nil { return nil, err } |