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.
5 // +build aix darwin dragonfly freebsd linux nacl netbsd openbsd solaris
18 // Network file descriptor.
20 // locking/lifetime of sysfd + serialize access to Read and Write methods
23 // immutable until Close
34 iovecs
*[]syscall
.Iovec
43 func newFD(sysfd
, family
, sotype
int, net
string) (*netFD
, error
) {
44 return &netFD
{sysfd
: sysfd
, family
: family
, sotype
: sotype
, net
: net
, isStream
: sotype
== syscall
.SOCK_STREAM
}, nil
47 func (fd
*netFD
) init() error
{
48 if err
:= fd
.pd
.init(fd
); err
!= nil {
54 func (fd
*netFD
) setAddr(laddr
, raddr Addr
) {
57 runtime
.SetFinalizer(fd
, (*netFD
).Close
)
60 func (fd
*netFD
) name() string {
63 ls
= fd
.laddr
.String()
66 rs
= fd
.raddr
.String()
68 return fd
.net
+ ":" + ls
+ "->" + rs
71 func (fd
*netFD
) connect(ctx context
.Context
, la
, ra syscall
.Sockaddr
) (ret error
) {
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.
75 switch err
:= connectFunc(fd
.sysfd
, ra
); err
{
76 case syscall
.EINPROGRESS
, syscall
.EALREADY
, syscall
.EINTR
:
77 case nil, syscall
.EISCONN
:
80 return mapErr(ctx
.Err())
83 if err
:= fd
.init(); err
!= nil {
88 // On Solaris we can see EINVAL if the socket has
89 // already been accepted and closed by the server.
90 // Treat this as a successful connection--writes to
91 // the socket will see EOF. For details and a test
92 // case in C see https://golang.org/issue/6828.
93 if runtime
.GOOS
== "solaris" {
98 return os
.NewSyscallError("connect", err
)
100 if err
:= fd
.init(); err
!= nil {
103 if deadline
, _
:= ctx
.Deadline(); !deadline
.IsZero() {
104 fd
.setWriteDeadline(deadline
)
105 defer fd
.setWriteDeadline(noDeadline
)
108 // Start the "interrupter" goroutine, if this context might be canceled.
109 // (The background context cannot)
111 // The interrupter goroutine waits for the context to be done and
112 // interrupts the dial (by altering the fd's write deadline, which
113 // wakes up waitWrite).
114 if ctx
!= context
.Background() {
115 // Wait for the interrupter goroutine to exit before returning
117 done
:= make(chan struct{})
118 interruptRes
:= make(chan error
)
121 if ctxErr
:= <-interruptRes
; ctxErr
!= nil && ret
== nil {
122 // The interrupter goroutine called setWriteDeadline,
123 // but the connect code below had returned from
124 // waitWrite already and did a successful connect (ret
125 // == nil). Because we've now poisoned the connection
126 // by making it unwritable, don't return a successful
127 // dial. This was issue 16523.
129 fd
.Close() // prevent a leak
135 // Force the runtime's poller to immediately give up
136 // waiting for writability, unblocking waitWrite
138 fd
.setWriteDeadline(aLongTimeAgo
)
139 testHookCanceledDial()
140 interruptRes
<- ctx
.Err()
148 // Performing multiple connect system calls on a
149 // non-blocking socket under Unix variants does not
150 // necessarily result in earlier errors being
151 // returned. Instead, once runtime-integrated network
152 // poller tells us that the socket is ready, get the
153 // SO_ERROR socket option to see if the connection
154 // succeeded or failed. See issue 7474 for further
156 if err
:= fd
.pd
.waitWrite(); err
!= nil {
159 return mapErr(ctx
.Err())
164 nerr
, err
:= getsockoptIntFunc(fd
.sysfd
, syscall
.SOL_SOCKET
, syscall
.SO_ERROR
)
166 return os
.NewSyscallError("getsockopt", err
)
168 switch err
:= syscall
.Errno(nerr
); err
{
169 case syscall
.EINPROGRESS
, syscall
.EALREADY
, syscall
.EINTR
:
170 case syscall
.Errno(0), syscall
.EISCONN
:
171 if runtime
.GOOS
!= "darwin" {
174 // See golang.org/issue/14548.
175 // On Darwin, multiple connect system calls on
176 // a non-blocking socket never harm SO_ERROR.
177 switch err
:= connectFunc(fd
.sysfd
, ra
); err
{
178 case nil, syscall
.EISCONN
:
182 return os
.NewSyscallError("getsockopt", err
)
187 func (fd
*netFD
) destroy() {
188 // Poller may want to unregister fd in readiness notification mechanism,
189 // so this must be executed before closeFunc.
193 runtime
.SetFinalizer(fd
, nil)
196 func (fd
*netFD
) Close() error
{
197 if !fd
.fdmu
.increfAndClose() {
200 // Unblock any I/O. Once it all unblocks and returns,
201 // so that it cannot be referring to fd.sysfd anymore,
202 // the final decref will close fd.sysfd. This should happen
203 // fairly quickly, since all the I/O is non-blocking, and any
204 // attempts to block in the pollDesc will return errClosing.
210 func (fd
*netFD
) shutdown(how
int) error
{
211 if err
:= fd
.incref(); err
!= nil {
215 return os
.NewSyscallError("shutdown", syscall
.Shutdown(fd
.sysfd
, how
))
218 func (fd
*netFD
) closeRead() error
{
219 return fd
.shutdown(syscall
.SHUT_RD
)
222 func (fd
*netFD
) closeWrite() error
{
223 return fd
.shutdown(syscall
.SHUT_WR
)
226 func (fd
*netFD
) Read(p
[]byte) (n
int, err error
) {
227 if err
:= fd
.readLock(); err
!= nil {
230 defer fd
.readUnlock()
232 // If the caller wanted a zero byte read, return immediately
233 // without trying. (But after acquiring the readLock.) Otherwise
234 // syscall.Read returns 0, nil and eofError turns that into
236 // TODO(bradfitz): make it wait for readability? (Issue 15735)
239 if err
:= fd
.pd
.prepareRead(); err
!= nil {
242 if fd
.isStream
&& len(p
) > 1<<30 {
246 n
, err
= syscall
.Read(fd
.sysfd
, p
)
249 if err
== syscall
.EAGAIN
{
250 if err
= fd
.pd
.waitRead(); err
== nil {
255 err
= fd
.eofError(n
, err
)
258 if _
, ok
:= err
.(syscall
.Errno
); ok
{
259 err
= os
.NewSyscallError("read", err
)
264 func (fd
*netFD
) readFrom(p
[]byte) (n
int, sa syscall
.Sockaddr
, err error
) {
265 if err
:= fd
.readLock(); err
!= nil {
268 defer fd
.readUnlock()
269 if err
:= fd
.pd
.prepareRead(); err
!= nil {
273 n
, sa
, err
= syscall
.Recvfrom(fd
.sysfd
, p
, 0)
276 if err
== syscall
.EAGAIN
{
277 if err
= fd
.pd
.waitRead(); err
== nil {
282 err
= fd
.eofError(n
, err
)
285 if _
, ok
:= err
.(syscall
.Errno
); ok
{
286 err
= os
.NewSyscallError("recvfrom", err
)
291 func (fd
*netFD
) readMsg(p
[]byte, oob
[]byte) (n
, oobn
, flags
int, sa syscall
.Sockaddr
, err error
) {
292 if err
:= fd
.readLock(); err
!= nil {
293 return 0, 0, 0, nil, err
295 defer fd
.readUnlock()
296 if err
:= fd
.pd
.prepareRead(); err
!= nil {
297 return 0, 0, 0, nil, err
300 n
, oobn
, flags
, sa
, err
= syscall
.Recvmsg(fd
.sysfd
, p
, oob
, 0)
302 // TODO(dfc) should n and oobn be set to 0
303 if err
== syscall
.EAGAIN
{
304 if err
= fd
.pd
.waitRead(); err
== nil {
309 err
= fd
.eofError(n
, err
)
312 if _
, ok
:= err
.(syscall
.Errno
); ok
{
313 err
= os
.NewSyscallError("recvmsg", err
)
318 func (fd
*netFD
) Write(p
[]byte) (nn
int, err error
) {
319 if err
:= fd
.writeLock(); err
!= nil {
322 defer fd
.writeUnlock()
323 if err
:= fd
.pd
.prepareWrite(); err
!= nil {
329 if fd
.isStream
&& max
-nn
> 1<<30 {
332 n
, err
= syscall
.Write(fd
.sysfd
, p
[nn
:max
])
339 if err
== syscall
.EAGAIN
{
340 if err
= fd
.pd
.waitWrite(); err
== nil {
348 err
= io
.ErrUnexpectedEOF
352 if _
, ok
:= err
.(syscall
.Errno
); ok
{
353 err
= os
.NewSyscallError("write", err
)
358 func (fd
*netFD
) writeTo(p
[]byte, sa syscall
.Sockaddr
) (n
int, err error
) {
359 if err
:= fd
.writeLock(); err
!= nil {
362 defer fd
.writeUnlock()
363 if err
:= fd
.pd
.prepareWrite(); err
!= nil {
367 err
= syscall
.Sendto(fd
.sysfd
, p
, 0, sa
)
368 if err
== syscall
.EAGAIN
{
369 if err
= fd
.pd
.waitWrite(); err
== nil {
378 if _
, ok
:= err
.(syscall
.Errno
); ok
{
379 err
= os
.NewSyscallError("sendto", err
)
384 func (fd
*netFD
) writeMsg(p
[]byte, oob
[]byte, sa syscall
.Sockaddr
) (n
int, oobn
int, err error
) {
385 if err
:= fd
.writeLock(); err
!= nil {
388 defer fd
.writeUnlock()
389 if err
:= fd
.pd
.prepareWrite(); err
!= nil {
393 n
, err
= syscall
.SendmsgN(fd
.sysfd
, p
, oob
, sa
, 0)
394 if err
== syscall
.EAGAIN
{
395 if err
= fd
.pd
.waitWrite(); err
== nil {
404 if _
, ok
:= err
.(syscall
.Errno
); ok
{
405 err
= os
.NewSyscallError("sendmsg", err
)
410 func (fd
*netFD
) accept() (netfd
*netFD
, err error
) {
411 if err
:= fd
.readLock(); err
!= nil {
414 defer fd
.readUnlock()
417 var rsa syscall
.Sockaddr
418 if err
= fd
.pd
.prepareRead(); err
!= nil {
422 s
, rsa
, err
= accept(fd
.sysfd
)
424 nerr
, ok
:= err
.(*os
.SyscallError
)
430 if err
= fd
.pd
.waitRead(); err
== nil {
433 case syscall
.ECONNABORTED
:
434 // This means that a socket on the
435 // listen queue was closed before we
436 // Accept()ed it; it's a silly error,
445 if netfd
, err
= newFD(s
, fd
.family
, fd
.sotype
, fd
.net
); err
!= nil {
449 if err
= netfd
.init(); err
!= nil {
453 lsa
, _
:= syscall
.Getsockname(netfd
.sysfd
)
454 netfd
.setAddr(netfd
.addrFunc()(lsa
), netfd
.addrFunc()(rsa
))
458 // Use a helper function to call fcntl. This is defined in C in
460 //extern __go_fcntl_uintptr
461 func fcntl(uintptr, uintptr, uintptr) (uintptr, uintptr)
463 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
464 // If the kernel doesn't support it, this is set to 0.
465 var tryDupCloexec
= int32(1)
467 func dupCloseOnExec(fd
int) (newfd
int, err error
) {
468 if atomic
.LoadInt32(&tryDupCloexec
) == 1 && syscall
.F_DUPFD_CLOEXEC
!= 0 {
469 syscall
.Entersyscall()
470 r0
, errno
:= fcntl(uintptr(fd
), syscall
.F_DUPFD_CLOEXEC
, 0)
471 syscall
.Exitsyscall()
472 e1
:= syscall
.Errno(errno
)
473 if runtime
.GOOS
== "darwin" && e1
== syscall
.EBADF
{
474 // On OS X 10.6 and below (but we only support
475 // >= 10.6), F_DUPFD_CLOEXEC is unsupported
476 // and fcntl there falls back (undocumented)
477 // to doing an ioctl instead, returning EBADF
478 // in this case because fd is not of the
479 // expected device fd type. Treat it as
480 // EINVAL instead, so we fall back to the
482 // TODO: only do this on 10.6 if we can detect 10.6
490 // Old kernel. Fall back to the portable way
492 atomic
.StoreInt32(&tryDupCloexec
, 0)
494 return -1, os
.NewSyscallError("fcntl", e1
)
497 return dupCloseOnExecOld(fd
)
500 // dupCloseOnExecUnixOld is the traditional way to dup an fd and
501 // set its O_CLOEXEC bit, using two system calls.
502 func dupCloseOnExecOld(fd
int) (newfd
int, err error
) {
503 syscall
.ForkLock
.RLock()
504 defer syscall
.ForkLock
.RUnlock()
505 newfd
, err
= syscall
.Dup(fd
)
507 return -1, os
.NewSyscallError("dup", err
)
509 syscall
.CloseOnExec(newfd
)
513 func (fd
*netFD
) dup() (f
*os
.File
, err error
) {
514 ns
, err
:= dupCloseOnExec(fd
.sysfd
)
519 // We want blocking mode for the new fd, hence the double negative.
520 // This also puts the old fd into blocking mode, meaning that
521 // I/O will block the thread instead of letting us use the epoll server.
522 // Everything will still work, just with more threads.
523 if err
= syscall
.SetNonblock(ns
, false); err
!= nil {
524 return nil, os
.NewSyscallError("setnonblock", err
)
527 return os
.NewFile(uintptr(ns
), fd
.name()), nil