* gcc-interface/decl.c (warn_on_field_placement): Issue the warning
[official-gcc.git] / libgo / go / net / fd_unix.go
blobb6ee05976dd415b62ece23396ad0cc1ecbbffe20
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
7 package net
9 import (
10 "context"
11 "io"
12 "os"
13 "runtime"
14 "sync/atomic"
15 "syscall"
18 // Network file descriptor.
19 type netFD struct {
20 // locking/lifetime of sysfd + serialize access to Read and Write methods
21 fdmu fdMutex
23 // immutable until Close
24 sysfd int
25 family int
26 sotype int
27 isStream bool
28 isConnected bool
29 net string
30 laddr Addr
31 raddr Addr
33 // writev cache.
34 iovecs *[]syscall.Iovec
36 // wait server
37 pd pollDesc
40 func sysInit() {
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 {
49 return err
51 return nil
54 func (fd *netFD) setAddr(laddr, raddr Addr) {
55 fd.laddr = laddr
56 fd.raddr = raddr
57 runtime.SetFinalizer(fd, (*netFD).Close)
60 func (fd *netFD) name() string {
61 var ls, rs string
62 if fd.laddr != nil {
63 ls = fd.laddr.String()
65 if fd.raddr != nil {
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:
78 select {
79 case <-ctx.Done():
80 return mapErr(ctx.Err())
81 default:
83 if err := fd.init(); err != nil {
84 return err
86 return nil
87 case syscall.EINVAL:
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" {
94 return nil
96 fallthrough
97 default:
98 return os.NewSyscallError("connect", err)
100 if err := fd.init(); err != nil {
101 return err
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
116 // from connect.
117 done := make(chan struct{})
118 interruptRes := make(chan error)
119 defer func() {
120 close(done)
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.
128 ret = ctxErr
129 fd.Close() // prevent a leak
132 go func() {
133 select {
134 case <-ctx.Done():
135 // Force the runtime's poller to immediately give up
136 // waiting for writability, unblocking waitWrite
137 // below.
138 fd.setWriteDeadline(aLongTimeAgo)
139 testHookCanceledDial()
140 interruptRes <- ctx.Err()
141 case <-done:
142 interruptRes <- nil
147 for {
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
155 // details.
156 if err := fd.pd.waitWrite(); err != nil {
157 select {
158 case <-ctx.Done():
159 return mapErr(ctx.Err())
160 default:
162 return err
164 nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
165 if err != nil {
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" {
172 return nil
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:
179 return nil
181 default:
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.
190 fd.pd.close()
191 closeFunc(fd.sysfd)
192 fd.sysfd = -1
193 runtime.SetFinalizer(fd, nil)
196 func (fd *netFD) Close() error {
197 if !fd.fdmu.increfAndClose() {
198 return errClosing
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.
205 fd.pd.evict()
206 fd.decref()
207 return nil
210 func (fd *netFD) shutdown(how int) error {
211 if err := fd.incref(); err != nil {
212 return err
214 defer fd.decref()
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 {
228 return 0, err
230 defer fd.readUnlock()
231 if len(p) == 0 {
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
235 // io.EOF.
236 // TODO(bradfitz): make it wait for readability? (Issue 15735)
237 return 0, nil
239 if err := fd.pd.prepareRead(); err != nil {
240 return 0, err
242 if fd.isStream && len(p) > 1<<30 {
243 p = p[:1<<30]
245 for {
246 n, err = syscall.Read(fd.sysfd, p)
247 if err != nil {
248 n = 0
249 if err == syscall.EAGAIN {
250 if err = fd.pd.waitRead(); err == nil {
251 continue
255 err = fd.eofError(n, err)
256 break
258 if _, ok := err.(syscall.Errno); ok {
259 err = os.NewSyscallError("read", err)
261 return
264 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
265 if err := fd.readLock(); err != nil {
266 return 0, nil, err
268 defer fd.readUnlock()
269 if err := fd.pd.prepareRead(); err != nil {
270 return 0, nil, err
272 for {
273 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
274 if err != nil {
275 n = 0
276 if err == syscall.EAGAIN {
277 if err = fd.pd.waitRead(); err == nil {
278 continue
282 err = fd.eofError(n, err)
283 break
285 if _, ok := err.(syscall.Errno); ok {
286 err = os.NewSyscallError("recvfrom", err)
288 return
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
299 for {
300 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
301 if err != nil {
302 // TODO(dfc) should n and oobn be set to 0
303 if err == syscall.EAGAIN {
304 if err = fd.pd.waitRead(); err == nil {
305 continue
309 err = fd.eofError(n, err)
310 break
312 if _, ok := err.(syscall.Errno); ok {
313 err = os.NewSyscallError("recvmsg", err)
315 return
318 func (fd *netFD) Write(p []byte) (nn int, err error) {
319 if err := fd.writeLock(); err != nil {
320 return 0, err
322 defer fd.writeUnlock()
323 if err := fd.pd.prepareWrite(); err != nil {
324 return 0, err
326 for {
327 var n int
328 max := len(p)
329 if fd.isStream && max-nn > 1<<30 {
330 max = nn + 1<<30
332 n, err = syscall.Write(fd.sysfd, p[nn:max])
333 if n > 0 {
334 nn += n
336 if nn == len(p) {
337 break
339 if err == syscall.EAGAIN {
340 if err = fd.pd.waitWrite(); err == nil {
341 continue
344 if err != nil {
345 break
347 if n == 0 {
348 err = io.ErrUnexpectedEOF
349 break
352 if _, ok := err.(syscall.Errno); ok {
353 err = os.NewSyscallError("write", err)
355 return nn, err
358 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
359 if err := fd.writeLock(); err != nil {
360 return 0, err
362 defer fd.writeUnlock()
363 if err := fd.pd.prepareWrite(); err != nil {
364 return 0, err
366 for {
367 err = syscall.Sendto(fd.sysfd, p, 0, sa)
368 if err == syscall.EAGAIN {
369 if err = fd.pd.waitWrite(); err == nil {
370 continue
373 break
375 if err == nil {
376 n = len(p)
378 if _, ok := err.(syscall.Errno); ok {
379 err = os.NewSyscallError("sendto", err)
381 return
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 {
386 return 0, 0, err
388 defer fd.writeUnlock()
389 if err := fd.pd.prepareWrite(); err != nil {
390 return 0, 0, err
392 for {
393 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0)
394 if err == syscall.EAGAIN {
395 if err = fd.pd.waitWrite(); err == nil {
396 continue
399 break
401 if err == nil {
402 oobn = len(oob)
404 if _, ok := err.(syscall.Errno); ok {
405 err = os.NewSyscallError("sendmsg", err)
407 return
410 func (fd *netFD) accept() (netfd *netFD, err error) {
411 if err := fd.readLock(); err != nil {
412 return nil, err
414 defer fd.readUnlock()
416 var s int
417 var rsa syscall.Sockaddr
418 if err = fd.pd.prepareRead(); err != nil {
419 return nil, err
421 for {
422 s, rsa, err = accept(fd.sysfd)
423 if err != nil {
424 nerr, ok := err.(*os.SyscallError)
425 if !ok {
426 return nil, err
428 switch nerr.Err {
429 case syscall.EAGAIN:
430 if err = fd.pd.waitRead(); err == nil {
431 continue
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,
437 // so try again.
438 continue
440 return nil, err
442 break
445 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
446 closeFunc(s)
447 return nil, err
449 if err = netfd.init(); err != nil {
450 fd.Close()
451 return nil, err
453 lsa, _ := syscall.Getsockname(netfd.sysfd)
454 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
455 return netfd, nil
458 // Use a helper function to call fcntl. This is defined in C in
459 // libgo/runtime.
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
481 // normal dup path.
482 // TODO: only do this on 10.6 if we can detect 10.6
483 // cheaply.
484 e1 = syscall.EINVAL
486 switch e1 {
487 case 0:
488 return int(r0), nil
489 case syscall.EINVAL:
490 // Old kernel. Fall back to the portable way
491 // from now on.
492 atomic.StoreInt32(&tryDupCloexec, 0)
493 default:
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)
506 if err != nil {
507 return -1, os.NewSyscallError("dup", err)
509 syscall.CloseOnExec(newfd)
510 return
513 func (fd *netFD) dup() (f *os.File, err error) {
514 ns, err := dupCloseOnExec(fd.sysfd)
515 if err != nil {
516 return nil, err
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