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 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
39 func dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
40 return dialer(deadline)
43 func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
44 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, 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(la, ra syscall.Sockaddr, deadline time.Time) 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 := syscall.Connect(fd.sysfd, ra); err {
76 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
77 case nil, syscall.EISCONN:
78 if !deadline.IsZero() && deadline.Before(time.Now()) {
81 if err := fd.init(); err != nil {
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
90 // case in C see http://golang.org/issue/6828.
91 if runtime.GOOS == "solaris" {
98 if err := fd.init(); err != nil {
101 if !deadline.IsZero() {
102 fd.setWriteDeadline(deadline)
103 defer fd.setWriteDeadline(noDeadline)
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
114 if err := fd.pd.WaitWrite(); err != nil {
117 nerr, err := syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
121 switch err := syscall.Errno(nerr); err {
122 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
123 case syscall.Errno(0), syscall.EISCONN:
131 func (fd *netFD) destroy() {
132 // Poller may want to unregister fd in readiness notification mechanism,
133 // so this must be executed before closesocket.
135 closesocket(fd.sysfd)
137 runtime.SetFinalizer(fd, nil)
140 // Add a reference to this fd.
141 // Returns an error if the fd cannot be used.
142 func (fd *netFD) incref() error {
143 if !fd.fdmu.Incref() {
149 // Remove a reference to this FD and close if we've been asked to do so
150 // (and there are no references left).
151 func (fd *netFD) decref() {
152 if fd.fdmu.Decref() {
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) {
166 // Unlock for reading and remove a reference to this FD.
167 func (fd *netFD) readUnlock() {
168 if fd.fdmu.RWUnlock(true) {
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) {
182 // Unlock for writing and remove a reference to this FD.
183 func (fd *netFD) writeUnlock() {
184 if fd.fdmu.RWUnlock(false) {
189 func (fd *netFD) Close() error {
190 fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
191 if !fd.fdmu.IncrefAndClose() {
195 // Unblock any I/O. Once it all unblocks and returns,
196 // so that it cannot be referring to fd.sysfd anymore,
197 // the final decref will close fd.sysfd. This should happen
198 // fairly quickly, since all the I/O is non-blocking, and any
199 // attempts to block in the pollDesc will return errClosing.
200 doWakeup := fd.pd.Evict()
209 func (fd *netFD) shutdown(how int) error {
210 if err := fd.incref(); err != nil {
214 err := syscall.Shutdown(fd.sysfd, how)
216 return &OpError{"shutdown", fd.net, fd.laddr, err}
221 func (fd *netFD) closeRead() error {
222 return fd.shutdown(syscall.SHUT_RD)
225 func (fd *netFD) closeWrite() error {
226 return fd.shutdown(syscall.SHUT_WR)
229 func (fd *netFD) Read(p []byte) (n int, err error) {
230 if err := fd.readLock(); err != nil {
233 defer fd.readUnlock()
234 if err := fd.pd.PrepareRead(); err != nil {
235 return 0, &OpError{"read", fd.net, fd.raddr, err}
238 n, err = syscall.Read(int(fd.sysfd), p)
241 if err == syscall.EAGAIN {
242 if err = fd.pd.WaitRead(); err == nil {
247 err = chkReadErr(n, err, fd)
250 if err != nil && err != io.EOF {
251 err = &OpError{"read", fd.net, fd.raddr, err}
256 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
257 if err := fd.readLock(); err != nil {
260 defer fd.readUnlock()
261 if err := fd.pd.PrepareRead(); err != nil {
262 return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
265 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
268 if err == syscall.EAGAIN {
269 if err = fd.pd.WaitRead(); err == nil {
274 err = chkReadErr(n, err, fd)
277 if err != nil && err != io.EOF {
278 err = &OpError{"read", fd.net, fd.laddr, err}
283 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
284 if err := fd.readLock(); err != nil {
285 return 0, 0, 0, nil, err
287 defer fd.readUnlock()
288 if err := fd.pd.PrepareRead(); err != nil {
289 return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
292 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
294 // TODO(dfc) should n and oobn be set to 0
295 if err == syscall.EAGAIN {
296 if err = fd.pd.WaitRead(); err == nil {
301 err = chkReadErr(n, err, fd)
304 if err != nil && err != io.EOF {
305 err = &OpError{"read", fd.net, fd.laddr, err}
310 func chkReadErr(n int, err error, fd *netFD) error {
311 if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
317 func (fd *netFD) Write(p []byte) (nn int, err error) {
318 if err := fd.writeLock(); err != nil {
321 defer fd.writeUnlock()
322 if err := fd.pd.PrepareWrite(); err != nil {
323 return 0, &OpError{"write", fd.net, fd.raddr, err}
327 n, err = syscall.Write(int(fd.sysfd), p[nn:])
334 if err == syscall.EAGAIN {
335 if err = fd.pd.WaitWrite(); err == nil {
344 err = io.ErrUnexpectedEOF
349 err = &OpError{"write", fd.net, fd.raddr, err}
354 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
355 if err := fd.writeLock(); err != nil {
358 defer fd.writeUnlock()
359 if err := fd.pd.PrepareWrite(); err != nil {
360 return 0, &OpError{"write", fd.net, fd.raddr, err}
363 err = syscall.Sendto(fd.sysfd, p, 0, sa)
364 if err == syscall.EAGAIN {
365 if err = fd.pd.WaitWrite(); err == nil {
374 err = &OpError{"write", fd.net, fd.raddr, err}
379 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
380 if err := fd.writeLock(); err != nil {
383 defer fd.writeUnlock()
384 if err := fd.pd.PrepareWrite(); err != nil {
385 return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
388 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0)
389 if err == syscall.EAGAIN {
390 if err = fd.pd.WaitWrite(); err == nil {
399 err = &OpError{"write", fd.net, fd.raddr, err}
404 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
405 if err := fd.readLock(); err != nil {
408 defer fd.readUnlock()
411 var rsa syscall.Sockaddr
412 if err = fd.pd.PrepareRead(); err != nil {
413 return nil, &OpError{"accept", fd.net, fd.laddr, err}
416 s, rsa, err = accept(fd.sysfd)
418 if err == syscall.EAGAIN {
419 if err = fd.pd.WaitRead(); err == nil {
422 } else if err == syscall.ECONNABORTED {
423 // This means that a socket on the listen queue was closed
424 // before we Accept()ed it; it's a silly error, so try again.
427 return nil, &OpError{"accept", fd.net, fd.laddr, err}
432 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
436 if err = netfd.init(); err != nil {
440 lsa, _ := syscall.Getsockname(netfd.sysfd)
441 netfd.setAddr(toAddr(lsa), toAddr(rsa))
445 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
446 // If the kernel doesn't support it, this is set to 0.
447 var tryDupCloexec = int32(1)
449 func dupCloseOnExec(fd int) (newfd int, err error) {
450 if atomic.LoadInt32(&tryDupCloexec) == 1 && syscall.F_DUPFD_CLOEXEC != 0 {
451 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
452 if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
453 // On OS X 10.6 and below (but we only support
454 // >= 10.6), F_DUPFD_CLOEXEC is unsupported
455 // and fcntl there falls back (undocumented)
456 // to doing an ioctl instead, returning EBADF
457 // in this case because fd is not of the
458 // expected device fd type. Treat it as
459 // EINVAL instead, so we fall back to the
461 // TODO: only do this on 10.6 if we can detect 10.6
469 // Old kernel. Fall back to the portable way
471 atomic.StoreInt32(&tryDupCloexec, 0)
476 return dupCloseOnExecOld(fd)
479 // dupCloseOnExecUnixOld is the traditional way to dup an fd and
480 // set its O_CLOEXEC bit, using two system calls.
481 func dupCloseOnExecOld(fd int) (newfd int, err error) {
482 syscall.ForkLock.RLock()
483 defer syscall.ForkLock.RUnlock()
484 newfd, err = syscall.Dup(fd)
488 syscall.CloseOnExec(newfd)
492 func (fd *netFD) dup() (f *os.File, err error) {
493 ns, err := dupCloseOnExec(fd.sysfd)
495 return nil, &OpError{"dup", fd.net, fd.laddr, err}
498 // We want blocking mode for the new fd, hence the double negative.
499 // This also puts the old fd into blocking mode, meaning that
500 // I/O will block the thread instead of letting us use the epoll server.
501 // Everything will still work, just with more threads.
502 if err = syscall.SetNonblock(ns, false); err != nil {
503 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
506 return os.NewFile(uintptr(ns), fd.name()), nil
509 func closesocket(s int) error {
510 return syscall.Close(s)
513 func skipRawSocketTests() (skip bool, skipmsg string, err error) {
514 if os.Getuid() != 0 {
515 return true, "skipping test; must be root", nil
517 return false, "", nil