Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 1 | // Copyright 2009 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
Dave Cheney | 7c8280c | 2014-02-25 09:47:42 -0500 | [diff] [blame] | 5 | // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris |
Russ Cox | 2715956 | 2011-09-15 16:48:57 -0400 | [diff] [blame] | 6 | |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 7 | package net |
| 8 | |
| 9 | import ( |
Russ Cox | 47a0533 | 2010-04-26 22:15:25 -0700 | [diff] [blame] | 10 | "io" |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 11 | "os" |
Dmitriy Vyukov | 3b6de5e | 2013-07-30 19:47:16 +0400 | [diff] [blame] | 12 | "runtime" |
Brad Fitzpatrick | 37feacf | 2013-08-05 15:43:45 -0700 | [diff] [blame] | 13 | "sync/atomic" |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 14 | "syscall" |
Russ Cox | 00f9f0c | 2010-03-30 10:34:57 -0700 | [diff] [blame] | 15 | "time" |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 16 | ) |
| 17 | |
Russ Cox | d8921c5 | 2009-02-15 14:18:39 -0800 | [diff] [blame] | 18 | // Network file descriptor. |
| 19 | type netFD struct { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 20 | // locking/lifetime of sysfd + serialize access to Read and Write methods |
| 21 | fdmu fdMutex |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 22 | |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 23 | // immutable until Close |
Mikio Hara | 974fa75 | 2012-01-27 01:31:42 +0900 | [diff] [blame] | 24 | sysfd int |
| 25 | family int |
| 26 | sotype int |
| 27 | isConnected bool |
Mikio Hara | 974fa75 | 2012-01-27 01:31:42 +0900 | [diff] [blame] | 28 | net string |
| 29 | laddr Addr |
| 30 | raddr Addr |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 31 | |
Sébastien Paolacci | 7014bc6 | 2012-09-26 15:32:59 -0400 | [diff] [blame] | 32 | // wait server |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 33 | pd pollDesc |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 34 | } |
| 35 | |
Alex Brainman | 1a94895 | 2013-05-20 15:23:45 +1000 | [diff] [blame] | 36 | func sysInit() { |
| 37 | } |
| 38 | |
Mikio Hara | 89b2676 | 2013-09-11 10:48:53 -0400 | [diff] [blame] | 39 | func dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) { |
| 40 | return dialer(deadline) |
Alex Brainman | 810e439 | 2013-01-11 12:42:09 +1100 | [diff] [blame] | 41 | } |
| 42 | |
Mikio Hara | 6a76bca36 | 2013-08-06 23:42:33 +0900 | [diff] [blame] | 43 | func newFD(sysfd, family, sotype int, net string) (*netFD, error) { |
| 44 | return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil |
| 45 | } |
| 46 | |
| 47 | func (fd *netFD) init() error { |
| 48 | if err := fd.pd.Init(fd); err != nil { |
| 49 | return err |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 50 | } |
Mikio Hara | 6a76bca36 | 2013-08-06 23:42:33 +0900 | [diff] [blame] | 51 | return nil |
Alexey Borzenkov | 2f45f72 | 2011-03-28 23:40:01 -0400 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | func (fd *netFD) setAddr(laddr, raddr Addr) { |
| 55 | fd.laddr = laddr |
| 56 | fd.raddr = raddr |
Dmitriy Vyukov | 3b6de5e | 2013-07-30 19:47:16 +0400 | [diff] [blame] | 57 | runtime.SetFinalizer(fd, (*netFD).Close) |
Dave Cheney | 067315c | 2012-10-26 19:41:21 +1100 | [diff] [blame] | 58 | } |
| 59 | |
| 60 | func (fd *netFD) name() string { |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 61 | var ls, rs string |
Dave Cheney | 067315c | 2012-10-26 19:41:21 +1100 | [diff] [blame] | 62 | if fd.laddr != nil { |
| 63 | ls = fd.laddr.String() |
Russ Cox | c83b838 | 2009-11-02 18:37:30 -0800 | [diff] [blame] | 64 | } |
Dave Cheney | 067315c | 2012-10-26 19:41:21 +1100 | [diff] [blame] | 65 | if fd.raddr != nil { |
| 66 | rs = fd.raddr.String() |
Russ Cox | c83b838 | 2009-11-02 18:37:30 -0800 | [diff] [blame] | 67 | } |
Dave Cheney | 067315c | 2012-10-26 19:41:21 +1100 | [diff] [blame] | 68 | return fd.net + ":" + ls + "->" + rs |
Alexey Borzenkov | 2f45f72 | 2011-03-28 23:40:01 -0400 | [diff] [blame] | 69 | } |
| 70 | |
Mikio Hara | c0325f5 | 2014-07-29 16:48:11 +0900 | [diff] [blame] | 71 | func (fd *netFD) connect(la, ra syscall.Sockaddr, deadline time.Time) error { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 72 | // Do not need to call fd.writeLock here, |
| 73 | // because fd is not yet accessible to user, |
| 74 | // so no concurrent operations are possible. |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 75 | switch err := connectFunc(fd.sysfd, ra); err { |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 76 | case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: |
| 77 | case nil, syscall.EISCONN: |
Mikio Hara | c0325f5 | 2014-07-29 16:48:11 +0900 | [diff] [blame] | 78 | if !deadline.IsZero() && deadline.Before(time.Now()) { |
| 79 | return errTimeout |
| 80 | } |
| 81 | if err := fd.init(); err != nil { |
| 82 | return err |
| 83 | } |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 84 | return nil |
| 85 | case syscall.EINVAL: |
Ian Lance Taylor | 672525a | 2013-12-28 09:37:54 -0800 | [diff] [blame] | 86 | // On Solaris we can see EINVAL if the socket has |
| 87 | // already been accepted and closed by the server. |
| 88 | // Treat this as a successful connection--writes to |
| 89 | // the socket will see EOF. For details and a test |
Brad Fitzpatrick | 2ae7737 | 2015-07-10 17:17:11 -0600 | [diff] [blame] | 90 | // case in C see https://golang.org/issue/6828. |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 91 | if runtime.GOOS == "solaris" { |
| 92 | return nil |
Ian Lance Taylor | 672525a | 2013-12-28 09:37:54 -0800 | [diff] [blame] | 93 | } |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 94 | fallthrough |
| 95 | default: |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 96 | return os.NewSyscallError("connect", err) |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 97 | } |
Mikio Hara | c0325f5 | 2014-07-29 16:48:11 +0900 | [diff] [blame] | 98 | if err := fd.init(); err != nil { |
| 99 | return err |
| 100 | } |
| 101 | if !deadline.IsZero() { |
| 102 | fd.setWriteDeadline(deadline) |
| 103 | defer fd.setWriteDeadline(noDeadline) |
| 104 | } |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 105 | for { |
| 106 | // Performing multiple connect system calls on a |
| 107 | // non-blocking socket under Unix variants does not |
| 108 | // necessarily result in earlier errors being |
| 109 | // returned. Instead, once runtime-integrated network |
| 110 | // poller tells us that the socket is ready, get the |
| 111 | // SO_ERROR socket option to see if the connection |
| 112 | // succeeded or failed. See issue 7474 for further |
| 113 | // details. |
| 114 | if err := fd.pd.WaitWrite(); err != nil { |
Dmitriy Vyukov | a11d7d4 | 2013-03-14 10:32:42 +0400 | [diff] [blame] | 115 | return err |
| 116 | } |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 117 | nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 118 | if err != nil { |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 119 | return os.NewSyscallError("getsockopt", err) |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 120 | } |
Mikio Hara | d1e3ad8 | 2014-03-25 02:56:10 +0900 | [diff] [blame] | 121 | switch err := syscall.Errno(nerr); err { |
| 122 | case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: |
| 123 | case syscall.Errno(0), syscall.EISCONN: |
| 124 | return nil |
| 125 | default: |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 126 | return os.NewSyscallError("getsockopt", err) |
Joel Sing | 734d463 | 2014-03-06 00:07:16 +1100 | [diff] [blame] | 127 | } |
Alexey Borzenkov | 2f45f72 | 2011-03-28 23:40:01 -0400 | [diff] [blame] | 128 | } |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 129 | } |
| 130 | |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 131 | func (fd *netFD) destroy() { |
| 132 | // Poller may want to unregister fd in readiness notification mechanism, |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 133 | // so this must be executed before closeFunc. |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 134 | fd.pd.Close() |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 135 | closeFunc(fd.sysfd) |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 136 | fd.sysfd = -1 |
| 137 | runtime.SetFinalizer(fd, nil) |
| 138 | } |
| 139 | |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 140 | // Add a reference to this fd. |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 141 | // Returns an error if the fd cannot be used. |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 142 | func (fd *netFD) incref() error { |
| 143 | if !fd.fdmu.Incref() { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 144 | return errClosing |
| 145 | } |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 146 | return nil |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 147 | } |
| 148 | |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 149 | // Remove a reference to this FD and close if we've been asked to do so |
| 150 | // (and there are no references left). |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 151 | func (fd *netFD) decref() { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 152 | if fd.fdmu.Decref() { |
| 153 | fd.destroy() |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 154 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 155 | } |
| 156 | |
| 157 | // Add a reference to this fd and lock for reading. |
| 158 | // Returns an error if the fd cannot be used. |
| 159 | func (fd *netFD) readLock() error { |
| 160 | if !fd.fdmu.RWLock(true) { |
| 161 | return errClosing |
| 162 | } |
| 163 | return nil |
| 164 | } |
| 165 | |
| 166 | // Unlock for reading and remove a reference to this FD. |
| 167 | func (fd *netFD) readUnlock() { |
| 168 | if fd.fdmu.RWUnlock(true) { |
| 169 | fd.destroy() |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | // Add a reference to this fd and lock for writing. |
| 174 | // Returns an error if the fd cannot be used. |
| 175 | func (fd *netFD) writeLock() error { |
| 176 | if !fd.fdmu.RWLock(false) { |
| 177 | return errClosing |
| 178 | } |
| 179 | return nil |
| 180 | } |
| 181 | |
| 182 | // Unlock for writing and remove a reference to this FD. |
| 183 | func (fd *netFD) writeUnlock() { |
| 184 | if fd.fdmu.RWUnlock(false) { |
| 185 | fd.destroy() |
| 186 | } |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 187 | } |
| 188 | |
Russ Cox | eb69292 | 2011-11-01 22:05:34 -0400 | [diff] [blame] | 189 | func (fd *netFD) Close() error { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 190 | if !fd.fdmu.IncrefAndClose() { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 191 | return errClosing |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 192 | } |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 193 | // Unblock any I/O. Once it all unblocks and returns, |
| 194 | // so that it cannot be referring to fd.sysfd anymore, |
| 195 | // the final decref will close fd.sysfd. This should happen |
| 196 | // fairly quickly, since all the I/O is non-blocking, and any |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 197 | // attempts to block in the pollDesc will return errClosing. |
Mikio Hara | c768a84 | 2015-02-04 18:00:52 +0900 | [diff] [blame] | 198 | fd.pd.Evict() |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 199 | fd.decref() |
| 200 | return nil |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 201 | } |
| 202 | |
Russ Cox | eb69292 | 2011-11-01 22:05:34 -0400 | [diff] [blame] | 203 | func (fd *netFD) shutdown(how int) error { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 204 | if err := fd.incref(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 205 | return err |
Brad Fitzpatrick | 394842e | 2011-09-28 08:12:38 -0700 | [diff] [blame] | 206 | } |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 207 | defer fd.decref() |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 208 | return os.NewSyscallError("shutdown", syscall.Shutdown(fd.sysfd, how)) |
Brad Fitzpatrick | 394842e | 2011-09-28 08:12:38 -0700 | [diff] [blame] | 209 | } |
| 210 | |
Mikio Hara | ebe5f20 | 2014-04-04 09:07:44 +0900 | [diff] [blame] | 211 | func (fd *netFD) closeRead() error { |
Albert Strasheim | 791b2a4 | 2011-10-12 13:45:25 -0400 | [diff] [blame] | 212 | return fd.shutdown(syscall.SHUT_RD) |
| 213 | } |
| 214 | |
Mikio Hara | ebe5f20 | 2014-04-04 09:07:44 +0900 | [diff] [blame] | 215 | func (fd *netFD) closeWrite() error { |
Albert Strasheim | 791b2a4 | 2011-10-12 13:45:25 -0400 | [diff] [blame] | 216 | return fd.shutdown(syscall.SHUT_WR) |
Brad Fitzpatrick | 394842e | 2011-09-28 08:12:38 -0700 | [diff] [blame] | 217 | } |
| 218 | |
Russ Cox | eb69292 | 2011-11-01 22:05:34 -0400 | [diff] [blame] | 219 | func (fd *netFD) Read(p []byte) (n int, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 220 | if err := fd.readLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 221 | return 0, err |
Michael Hoisie | 9192ec2 | 2010-05-20 17:13:50 -0700 | [diff] [blame] | 222 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 223 | defer fd.readUnlock() |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 224 | if err := fd.pd.PrepareRead(); err != nil { |
Mikio Hara | ec11444 | 2015-04-16 23:10:56 +0900 | [diff] [blame] | 225 | return 0, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 226 | } |
Russ Cox | a0bcaf4 | 2009-06-25 20:24:55 -0700 | [diff] [blame] | 227 | for { |
Mikio Hara | 64b1aa1 | 2015-05-11 18:02:27 +0900 | [diff] [blame] | 228 | n, err = syscall.Read(fd.sysfd, p) |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 229 | if err != nil { |
Dave Cheney | 73b3e23 | 2012-11-26 10:59:43 +1100 | [diff] [blame] | 230 | n = 0 |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 231 | if err == syscall.EAGAIN { |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 232 | if err = fd.pd.WaitRead(); err == nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 233 | continue |
| 234 | } |
| 235 | } |
Russ Cox | a0bcaf4 | 2009-06-25 20:24:55 -0700 | [diff] [blame] | 236 | } |
Mikio Hara | a877e81 | 2014-12-31 10:08:51 +0900 | [diff] [blame] | 237 | err = fd.eofError(n, err) |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 238 | break |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 239 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 240 | if _, ok := err.(syscall.Errno); ok { |
| 241 | err = os.NewSyscallError("read", err) |
| 242 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 243 | return |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 244 | } |
| 245 | |
Ian Lance Taylor | 7d299d0 | 2014-04-02 17:06:51 -0700 | [diff] [blame] | 246 | func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 247 | if err := fd.readLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 248 | return 0, nil, err |
| 249 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 250 | defer fd.readUnlock() |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 251 | if err := fd.pd.PrepareRead(); err != nil { |
Mikio Hara | ec11444 | 2015-04-16 23:10:56 +0900 | [diff] [blame] | 252 | return 0, nil, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 253 | } |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 254 | for { |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 255 | n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 256 | if err != nil { |
Dave Cheney | 73b3e23 | 2012-11-26 10:59:43 +1100 | [diff] [blame] | 257 | n = 0 |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 258 | if err == syscall.EAGAIN { |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 259 | if err = fd.pd.WaitRead(); err == nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 260 | continue |
| 261 | } |
| 262 | } |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 263 | } |
Mikio Hara | a877e81 | 2014-12-31 10:08:51 +0900 | [diff] [blame] | 264 | err = fd.eofError(n, err) |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 265 | break |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 266 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 267 | if _, ok := err.(syscall.Errno); ok { |
| 268 | err = os.NewSyscallError("recvfrom", err) |
| 269 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 270 | return |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 271 | } |
| 272 | |
Ian Lance Taylor | 7d299d0 | 2014-04-02 17:06:51 -0700 | [diff] [blame] | 273 | func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 274 | if err := fd.readLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 275 | return 0, 0, 0, nil, err |
| 276 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 277 | defer fd.readUnlock() |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 278 | if err := fd.pd.PrepareRead(); err != nil { |
Mikio Hara | ec11444 | 2015-04-16 23:10:56 +0900 | [diff] [blame] | 279 | return 0, 0, 0, nil, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 280 | } |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 281 | for { |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 282 | n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 283 | if err != nil { |
Dave Cheney | 9fb9699 | 2012-12-05 15:59:01 +1100 | [diff] [blame] | 284 | // TODO(dfc) should n and oobn be set to 0 |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 285 | if err == syscall.EAGAIN { |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 286 | if err = fd.pd.WaitRead(); err == nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 287 | continue |
| 288 | } |
| 289 | } |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 290 | } |
Mikio Hara | a877e81 | 2014-12-31 10:08:51 +0900 | [diff] [blame] | 291 | err = fd.eofError(n, err) |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 292 | break |
| 293 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 294 | if _, ok := err.(syscall.Errno); ok { |
| 295 | err = os.NewSyscallError("recvmsg", err) |
| 296 | } |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 297 | return |
| 298 | } |
| 299 | |
Dave Cheney | 9fb9699 | 2012-12-05 15:59:01 +1100 | [diff] [blame] | 300 | func (fd *netFD) Write(p []byte) (nn int, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 301 | if err := fd.writeLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 302 | return 0, err |
| 303 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 304 | defer fd.writeUnlock() |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 305 | if err := fd.pd.PrepareWrite(); err != nil { |
Mikio Hara | 11b5f98 | 2015-04-16 11:26:44 +0900 | [diff] [blame] | 306 | return 0, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 307 | } |
Russ Cox | 47a0533 | 2010-04-26 22:15:25 -0700 | [diff] [blame] | 308 | for { |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 309 | var n int |
Mikio Hara | 64b1aa1 | 2015-05-11 18:02:27 +0900 | [diff] [blame] | 310 | n, err = syscall.Write(fd.sysfd, p[nn:]) |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 311 | if n > 0 { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 312 | nn += n |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 313 | } |
Russ Cox | 1e37e8a | 2009-03-06 17:51:31 -0800 | [diff] [blame] | 314 | if nn == len(p) { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 315 | break |
Russ Cox | 1e37e8a | 2009-03-06 17:51:31 -0800 | [diff] [blame] | 316 | } |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 317 | if err == syscall.EAGAIN { |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 318 | if err = fd.pd.WaitWrite(); err == nil { |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 319 | continue |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 320 | } |
Russ Cox | 1e37e8a | 2009-03-06 17:51:31 -0800 | [diff] [blame] | 321 | } |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 322 | if err != nil { |
Robert Griesemer | 40621d5 | 2009-11-09 12:07:39 -0800 | [diff] [blame] | 323 | break |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 324 | } |
Russ Cox | 47a0533 | 2010-04-26 22:15:25 -0700 | [diff] [blame] | 325 | if n == 0 { |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 326 | err = io.ErrUnexpectedEOF |
Russ Cox | 47a0533 | 2010-04-26 22:15:25 -0700 | [diff] [blame] | 327 | break |
| 328 | } |
| 329 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 330 | if _, ok := err.(syscall.Errno); ok { |
| 331 | err = os.NewSyscallError("write", err) |
| 332 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 333 | return nn, err |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 334 | } |
| 335 | |
Ian Lance Taylor | 7d299d0 | 2014-04-02 17:06:51 -0700 | [diff] [blame] | 336 | func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 337 | if err := fd.writeLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 338 | return 0, err |
| 339 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 340 | defer fd.writeUnlock() |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 341 | if err := fd.pd.PrepareWrite(); err != nil { |
Mikio Hara | 11b5f98 | 2015-04-16 11:26:44 +0900 | [diff] [blame] | 342 | return 0, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 343 | } |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 344 | for { |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 345 | err = syscall.Sendto(fd.sysfd, p, 0, sa) |
| 346 | if err == syscall.EAGAIN { |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 347 | if err = fd.pd.WaitWrite(); err == nil { |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 348 | continue |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 349 | } |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 350 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 351 | break |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 352 | } |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 353 | if err == nil { |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 354 | n = len(p) |
| 355 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 356 | if _, ok := err.(syscall.Errno); ok { |
| 357 | err = os.NewSyscallError("sendto", err) |
| 358 | } |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 359 | return |
Russ Cox | 6e788e0 | 2009-11-17 08:39:17 -0800 | [diff] [blame] | 360 | } |
| 361 | |
Ian Lance Taylor | 7d299d0 | 2014-04-02 17:06:51 -0700 | [diff] [blame] | 362 | func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 363 | if err := fd.writeLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 364 | return 0, 0, err |
| 365 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 366 | defer fd.writeUnlock() |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 367 | if err := fd.pd.PrepareWrite(); err != nil { |
Mikio Hara | 11b5f98 | 2015-04-16 11:26:44 +0900 | [diff] [blame] | 368 | return 0, 0, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 369 | } |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 370 | for { |
Mikio Hara | e419ab6 | 2014-04-26 06:52:37 +0900 | [diff] [blame] | 371 | n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 372 | if err == syscall.EAGAIN { |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 373 | if err = fd.pd.WaitWrite(); err == nil { |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 374 | continue |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 375 | } |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 376 | } |
| 377 | break |
| 378 | } |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 379 | if err == nil { |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 380 | oobn = len(oob) |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 381 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 382 | if _, ok := err.(syscall.Errno); ok { |
| 383 | err = os.NewSyscallError("sendmsg", err) |
| 384 | } |
Albert Strasheim | cf6c212 | 2010-12-07 13:40:14 -0500 | [diff] [blame] | 385 | return |
| 386 | } |
| 387 | |
Mikio Hara | 5c055e7 | 2014-08-05 06:10:46 +0900 | [diff] [blame] | 388 | func (fd *netFD) accept() (netfd *netFD, err error) { |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 389 | if err := fd.readLock(); err != nil { |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 390 | return nil, err |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 391 | } |
Dmitriy Vyukov | 23e15f7 | 2013-08-09 21:43:00 +0400 | [diff] [blame] | 392 | defer fd.readUnlock() |
Devon H. O'Dell | eb16346 | 2009-12-01 23:28:57 -0800 | [diff] [blame] | 393 | |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 394 | var s int |
Mikio Hara | c20ced9 | 2011-08-16 16:53:09 -0400 | [diff] [blame] | 395 | var rsa syscall.Sockaddr |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 396 | if err = fd.pd.PrepareRead(); err != nil { |
Mikio Hara | 4540e16 | 2015-04-17 14:35:54 +0900 | [diff] [blame] | 397 | return nil, err |
Dmitriy Vyukov | 0f136f2 | 2013-03-07 17:03:40 +0400 | [diff] [blame] | 398 | } |
Russ Cox | d8921c5 | 2009-02-15 14:18:39 -0800 | [diff] [blame] | 399 | for { |
Ian Lance Taylor | 31f58dc | 2013-01-28 08:54:15 -0800 | [diff] [blame] | 400 | s, rsa, err = accept(fd.sysfd) |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 401 | if err != nil { |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 402 | nerr, ok := err.(*os.SyscallError) |
| 403 | if !ok { |
| 404 | return nil, err |
| 405 | } |
| 406 | switch nerr.Err { |
| 407 | case syscall.EAGAIN: |
Dmitriy Vyukov | b09d881 | 2013-03-13 00:03:00 +0400 | [diff] [blame] | 408 | if err = fd.pd.WaitRead(); err == nil { |
Dave Cheney | 28b59942 | 2012-11-28 11:29:25 +1100 | [diff] [blame] | 409 | continue |
Russ Cox | 5e4e3d8 | 2012-02-14 00:40:37 -0500 | [diff] [blame] | 410 | } |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 411 | case syscall.ECONNABORTED: |
| 412 | // This means that a socket on the |
| 413 | // listen queue was closed before we |
| 414 | // Accept()ed it; it's a silly error, |
| 415 | // so try again. |
Devon H. O'Dell | a63c37b | 2012-03-27 00:06:14 -0400 | [diff] [blame] | 416 | continue |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 417 | } |
Mikio Hara | 4540e16 | 2015-04-17 14:35:54 +0900 | [diff] [blame] | 418 | return nil, err |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 419 | } |
| 420 | break |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 421 | } |
Russ Cox | d8921c5 | 2009-02-15 14:18:39 -0800 | [diff] [blame] | 422 | |
Mikio Hara | 28397be | 2012-02-01 00:36:45 +0900 | [diff] [blame] | 423 | if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { |
Mikio Hara | 29d1f3b | 2015-03-01 12:27:01 +0900 | [diff] [blame] | 424 | closeFunc(s) |
Robert Griesemer | a3d1045 | 2009-12-15 15:35:38 -0800 | [diff] [blame] | 425 | return nil, err |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 426 | } |
Mikio Hara | 6a76bca36 | 2013-08-06 23:42:33 +0900 | [diff] [blame] | 427 | if err = netfd.init(); err != nil { |
| 428 | fd.Close() |
| 429 | return nil, err |
| 430 | } |
Mikio Hara | e4389c0 | 2012-09-19 01:33:03 +0900 | [diff] [blame] | 431 | lsa, _ := syscall.Getsockname(netfd.sysfd) |
Mikio Hara | 5c055e7 | 2014-08-05 06:10:46 +0900 | [diff] [blame] | 432 | netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) |
Mikio Hara | 28397be | 2012-02-01 00:36:45 +0900 | [diff] [blame] | 433 | return netfd, nil |
Russ Cox | e4a61c6 | 2008-09-29 13:37:00 -0700 | [diff] [blame] | 434 | } |
Keith Rarick | a144e3e | 2010-11-05 14:02:03 -0400 | [diff] [blame] | 435 | |
Brad Fitzpatrick | 37feacf | 2013-08-05 15:43:45 -0700 | [diff] [blame] | 436 | // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. |
| 437 | // If the kernel doesn't support it, this is set to 0. |
| 438 | var tryDupCloexec = int32(1) |
| 439 | |
| 440 | func dupCloseOnExec(fd int) (newfd int, err error) { |
| 441 | if atomic.LoadInt32(&tryDupCloexec) == 1 { |
| 442 | r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) |
Brad Fitzpatrick | b2fcdfa | 2013-08-06 07:18:06 -0700 | [diff] [blame] | 443 | if runtime.GOOS == "darwin" && e1 == syscall.EBADF { |
| 444 | // On OS X 10.6 and below (but we only support |
| 445 | // >= 10.6), F_DUPFD_CLOEXEC is unsupported |
| 446 | // and fcntl there falls back (undocumented) |
| 447 | // to doing an ioctl instead, returning EBADF |
| 448 | // in this case because fd is not of the |
| 449 | // expected device fd type. Treat it as |
| 450 | // EINVAL instead, so we fall back to the |
| 451 | // normal dup path. |
| 452 | // TODO: only do this on 10.6 if we can detect 10.6 |
| 453 | // cheaply. |
| 454 | e1 = syscall.EINVAL |
| 455 | } |
Brad Fitzpatrick | 37feacf | 2013-08-05 15:43:45 -0700 | [diff] [blame] | 456 | switch e1 { |
| 457 | case 0: |
| 458 | return int(r0), nil |
| 459 | case syscall.EINVAL: |
| 460 | // Old kernel. Fall back to the portable way |
| 461 | // from now on. |
| 462 | atomic.StoreInt32(&tryDupCloexec, 0) |
| 463 | default: |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 464 | return -1, os.NewSyscallError("fcntl", e1) |
Brad Fitzpatrick | 37feacf | 2013-08-05 15:43:45 -0700 | [diff] [blame] | 465 | } |
| 466 | } |
| 467 | return dupCloseOnExecOld(fd) |
| 468 | } |
| 469 | |
| 470 | // dupCloseOnExecUnixOld is the traditional way to dup an fd and |
| 471 | // set its O_CLOEXEC bit, using two system calls. |
| 472 | func dupCloseOnExecOld(fd int) (newfd int, err error) { |
Brad Fitzpatrick | 2d2866e | 2012-08-06 14:12:23 +1000 | [diff] [blame] | 473 | syscall.ForkLock.RLock() |
Brad Fitzpatrick | 37feacf | 2013-08-05 15:43:45 -0700 | [diff] [blame] | 474 | defer syscall.ForkLock.RUnlock() |
| 475 | newfd, err = syscall.Dup(fd) |
| 476 | if err != nil { |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 477 | return -1, os.NewSyscallError("dup", err) |
Brad Fitzpatrick | 37feacf | 2013-08-05 15:43:45 -0700 | [diff] [blame] | 478 | } |
| 479 | syscall.CloseOnExec(newfd) |
| 480 | return |
| 481 | } |
| 482 | |
| 483 | func (fd *netFD) dup() (f *os.File, err error) { |
| 484 | ns, err := dupCloseOnExec(fd.sysfd) |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 485 | if err != nil { |
Mikio Hara | 8851113 | 2015-04-18 16:53:55 +0900 | [diff] [blame] | 486 | return nil, err |
Keith Rarick | a144e3e | 2010-11-05 14:02:03 -0400 | [diff] [blame] | 487 | } |
| 488 | |
| 489 | // We want blocking mode for the new fd, hence the double negative. |
Russ Cox | 18441e8 | 2013-02-07 22:45:12 -0500 | [diff] [blame] | 490 | // This also puts the old fd into blocking mode, meaning that |
| 491 | // I/O will block the thread instead of letting us use the epoll server. |
| 492 | // Everything will still work, just with more threads. |
Russ Cox | c017a82 | 2011-11-13 22:44:52 -0500 | [diff] [blame] | 493 | if err = syscall.SetNonblock(ns, false); err != nil { |
Mikio Hara | 055ecb7 | 2015-04-21 21:20:15 +0900 | [diff] [blame] | 494 | return nil, os.NewSyscallError("setnonblock", err) |
Keith Rarick | a144e3e | 2010-11-05 14:02:03 -0400 | [diff] [blame] | 495 | } |
| 496 | |
Dave Cheney | 067315c | 2012-10-26 19:41:21 +1100 | [diff] [blame] | 497 | return os.NewFile(uintptr(ns), fd.name()), nil |
Keith Rarick | a144e3e | 2010-11-05 14:02:03 -0400 | [diff] [blame] | 498 | } |