github.com/brownsys/tracing-framework-go@v0.0.0-20161210174012-0542a62412fe/go/darwin_amd64/src/net/fd_unix.go (about) 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 5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris 6 7 package net 8 9 import ( 10 "context" 11 "io" 12 "os" 13 "runtime" 14 "sync/atomic" 15 "syscall" 16 ) 17 18 // Network file descriptor. 19 type netFD struct { 20 // locking/lifetime of sysfd + serialize access to Read and Write methods 21 fdmu fdMutex 22 23 // immutable until Close 24 sysfd int 25 family int 26 sotype int 27 isConnected bool 28 net string 29 laddr Addr 30 raddr Addr 31 32 // wait server 33 pd pollDesc 34 } 35 36 func sysInit() { 37 } 38 39 func newFD(sysfd, family, sotype int, net string) (*netFD, error) { 40 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil 41 } 42 43 func (fd *netFD) init() error { 44 if err := fd.pd.init(fd); err != nil { 45 return err 46 } 47 return nil 48 } 49 50 func (fd *netFD) setAddr(laddr, raddr Addr) { 51 fd.laddr = laddr 52 fd.raddr = raddr 53 runtime.SetFinalizer(fd, (*netFD).Close) 54 } 55 56 func (fd *netFD) name() string { 57 var ls, rs string 58 if fd.laddr != nil { 59 ls = fd.laddr.String() 60 } 61 if fd.raddr != nil { 62 rs = fd.raddr.String() 63 } 64 return fd.net + ":" + ls + "->" + rs 65 } 66 67 func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret error) { 68 // Do not need to call fd.writeLock here, 69 // because fd is not yet accessible to user, 70 // so no concurrent operations are possible. 71 switch err := connectFunc(fd.sysfd, ra); err { 72 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: 73 case nil, syscall.EISCONN: 74 select { 75 case <-ctx.Done(): 76 return mapErr(ctx.Err()) 77 default: 78 } 79 if err := fd.init(); err != nil { 80 return err 81 } 82 return nil 83 case syscall.EINVAL: 84 // On Solaris we can see EINVAL if the socket has 85 // already been accepted and closed by the server. 86 // Treat this as a successful connection--writes to 87 // the socket will see EOF. For details and a test 88 // case in C see https://golang.org/issue/6828. 89 if runtime.GOOS == "solaris" { 90 return nil 91 } 92 fallthrough 93 default: 94 return os.NewSyscallError("connect", err) 95 } 96 if err := fd.init(); err != nil { 97 return err 98 } 99 if deadline, _ := ctx.Deadline(); !deadline.IsZero() { 100 fd.setWriteDeadline(deadline) 101 defer fd.setWriteDeadline(noDeadline) 102 } 103 104 // Start the "interrupter" goroutine, if this context might be canceled. 105 // (The background context cannot) 106 // 107 // The interrupter goroutine waits for the context to be done and 108 // interrupts the dial (by altering the fd's write deadline, which 109 // wakes up waitWrite). 110 if ctx != context.Background() { 111 // Wait for the interrupter goroutine to exit before returning 112 // from connect. 113 done := make(chan struct{}) 114 interruptRes := make(chan error) 115 defer func() { 116 close(done) 117 if ctxErr := <-interruptRes; ctxErr != nil && ret == nil { 118 // The interrupter goroutine called setWriteDeadline, 119 // but the connect code below had returned from 120 // waitWrite already and did a successful connect (ret 121 // == nil). Because we've now poisoned the connection 122 // by making it unwritable, don't return a successful 123 // dial. This was issue 16523. 124 ret = ctxErr 125 fd.Close() // prevent a leak 126 } 127 }() 128 go func() { 129 select { 130 case <-ctx.Done(): 131 // Force the runtime's poller to immediately give up 132 // waiting for writability, unblocking waitWrite 133 // below. 134 fd.setWriteDeadline(aLongTimeAgo) 135 testHookCanceledDial() 136 interruptRes <- ctx.Err() 137 case <-done: 138 interruptRes <- nil 139 } 140 }() 141 } 142 143 for { 144 // Performing multiple connect system calls on a 145 // non-blocking socket under Unix variants does not 146 // necessarily result in earlier errors being 147 // returned. Instead, once runtime-integrated network 148 // poller tells us that the socket is ready, get the 149 // SO_ERROR socket option to see if the connection 150 // succeeded or failed. See issue 7474 for further 151 // details. 152 if err := fd.pd.waitWrite(); err != nil { 153 select { 154 case <-ctx.Done(): 155 return mapErr(ctx.Err()) 156 default: 157 } 158 return err 159 } 160 nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) 161 if err != nil { 162 return os.NewSyscallError("getsockopt", err) 163 } 164 switch err := syscall.Errno(nerr); err { 165 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: 166 case syscall.Errno(0), syscall.EISCONN: 167 if runtime.GOOS != "darwin" { 168 return nil 169 } 170 // See golang.org/issue/14548. 171 // On Darwin, multiple connect system calls on 172 // a non-blocking socket never harm SO_ERROR. 173 switch err := connectFunc(fd.sysfd, ra); err { 174 case nil, syscall.EISCONN: 175 return nil 176 } 177 default: 178 return os.NewSyscallError("getsockopt", err) 179 } 180 } 181 } 182 183 func (fd *netFD) destroy() { 184 // Poller may want to unregister fd in readiness notification mechanism, 185 // so this must be executed before closeFunc. 186 fd.pd.close() 187 closeFunc(fd.sysfd) 188 fd.sysfd = -1 189 runtime.SetFinalizer(fd, nil) 190 } 191 192 func (fd *netFD) Close() error { 193 if !fd.fdmu.increfAndClose() { 194 return errClosing 195 } 196 // Unblock any I/O. Once it all unblocks and returns, 197 // so that it cannot be referring to fd.sysfd anymore, 198 // the final decref will close fd.sysfd. This should happen 199 // fairly quickly, since all the I/O is non-blocking, and any 200 // attempts to block in the pollDesc will return errClosing. 201 fd.pd.evict() 202 fd.decref() 203 return nil 204 } 205 206 func (fd *netFD) shutdown(how int) error { 207 if err := fd.incref(); err != nil { 208 return err 209 } 210 defer fd.decref() 211 return os.NewSyscallError("shutdown", syscall.Shutdown(fd.sysfd, how)) 212 } 213 214 func (fd *netFD) closeRead() error { 215 return fd.shutdown(syscall.SHUT_RD) 216 } 217 218 func (fd *netFD) closeWrite() error { 219 return fd.shutdown(syscall.SHUT_WR) 220 } 221 222 func (fd *netFD) Read(p []byte) (n int, err error) { 223 if err := fd.readLock(); err != nil { 224 return 0, err 225 } 226 defer fd.readUnlock() 227 if len(p) == 0 { 228 // If the caller wanted a zero byte read, return immediately 229 // without trying. (But after acquiring the readLock.) Otherwise 230 // syscall.Read returns 0, nil and eofError turns that into 231 // io.EOF. 232 // TODO(bradfitz): make it wait for readability? (Issue 15735) 233 return 0, nil 234 } 235 if err := fd.pd.prepareRead(); err != nil { 236 return 0, err 237 } 238 for { 239 n, err = syscall.Read(fd.sysfd, p) 240 if err != nil { 241 n = 0 242 if err == syscall.EAGAIN { 243 if err = fd.pd.waitRead(); err == nil { 244 continue 245 } 246 } 247 } 248 err = fd.eofError(n, err) 249 break 250 } 251 if _, ok := err.(syscall.Errno); ok { 252 err = os.NewSyscallError("read", err) 253 } 254 return 255 } 256 257 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 258 if err := fd.readLock(); err != nil { 259 return 0, nil, err 260 } 261 defer fd.readUnlock() 262 if err := fd.pd.prepareRead(); err != nil { 263 return 0, nil, err 264 } 265 for { 266 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) 267 if err != nil { 268 n = 0 269 if err == syscall.EAGAIN { 270 if err = fd.pd.waitRead(); err == nil { 271 continue 272 } 273 } 274 } 275 err = fd.eofError(n, err) 276 break 277 } 278 if _, ok := err.(syscall.Errno); ok { 279 err = os.NewSyscallError("recvfrom", err) 280 } 281 return 282 } 283 284 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 285 if err := fd.readLock(); err != nil { 286 return 0, 0, 0, nil, err 287 } 288 defer fd.readUnlock() 289 if err := fd.pd.prepareRead(); err != nil { 290 return 0, 0, 0, nil, err 291 } 292 for { 293 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) 294 if err != nil { 295 // TODO(dfc) should n and oobn be set to 0 296 if err == syscall.EAGAIN { 297 if err = fd.pd.waitRead(); err == nil { 298 continue 299 } 300 } 301 } 302 err = fd.eofError(n, err) 303 break 304 } 305 if _, ok := err.(syscall.Errno); ok { 306 err = os.NewSyscallError("recvmsg", err) 307 } 308 return 309 } 310 311 func (fd *netFD) Write(p []byte) (nn int, err error) { 312 if err := fd.writeLock(); err != nil { 313 return 0, err 314 } 315 defer fd.writeUnlock() 316 if err := fd.pd.prepareWrite(); err != nil { 317 return 0, err 318 } 319 for { 320 var n int 321 n, err = syscall.Write(fd.sysfd, p[nn:]) 322 if n > 0 { 323 nn += n 324 } 325 if nn == len(p) { 326 break 327 } 328 if err == syscall.EAGAIN { 329 if err = fd.pd.waitWrite(); err == nil { 330 continue 331 } 332 } 333 if err != nil { 334 break 335 } 336 if n == 0 { 337 err = io.ErrUnexpectedEOF 338 break 339 } 340 } 341 if _, ok := err.(syscall.Errno); ok { 342 err = os.NewSyscallError("write", err) 343 } 344 return nn, err 345 } 346 347 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 348 if err := fd.writeLock(); err != nil { 349 return 0, err 350 } 351 defer fd.writeUnlock() 352 if err := fd.pd.prepareWrite(); err != nil { 353 return 0, err 354 } 355 for { 356 err = syscall.Sendto(fd.sysfd, p, 0, sa) 357 if err == syscall.EAGAIN { 358 if err = fd.pd.waitWrite(); err == nil { 359 continue 360 } 361 } 362 break 363 } 364 if err == nil { 365 n = len(p) 366 } 367 if _, ok := err.(syscall.Errno); ok { 368 err = os.NewSyscallError("sendto", err) 369 } 370 return 371 } 372 373 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 374 if err := fd.writeLock(); err != nil { 375 return 0, 0, err 376 } 377 defer fd.writeUnlock() 378 if err := fd.pd.prepareWrite(); err != nil { 379 return 0, 0, err 380 } 381 for { 382 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) 383 if err == syscall.EAGAIN { 384 if err = fd.pd.waitWrite(); err == nil { 385 continue 386 } 387 } 388 break 389 } 390 if err == nil { 391 oobn = len(oob) 392 } 393 if _, ok := err.(syscall.Errno); ok { 394 err = os.NewSyscallError("sendmsg", err) 395 } 396 return 397 } 398 399 func (fd *netFD) accept() (netfd *netFD, err error) { 400 if err := fd.readLock(); err != nil { 401 return nil, err 402 } 403 defer fd.readUnlock() 404 405 var s int 406 var rsa syscall.Sockaddr 407 if err = fd.pd.prepareRead(); err != nil { 408 return nil, err 409 } 410 for { 411 s, rsa, err = accept(fd.sysfd) 412 if err != nil { 413 nerr, ok := err.(*os.SyscallError) 414 if !ok { 415 return nil, err 416 } 417 switch nerr.Err { 418 case syscall.EAGAIN: 419 if err = fd.pd.waitRead(); err == nil { 420 continue 421 } 422 case syscall.ECONNABORTED: 423 // This means that a socket on the 424 // listen queue was closed before we 425 // Accept()ed it; it's a silly error, 426 // so try again. 427 continue 428 } 429 return nil, err 430 } 431 break 432 } 433 434 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 435 closeFunc(s) 436 return nil, err 437 } 438 if err = netfd.init(); err != nil { 439 fd.Close() 440 return nil, err 441 } 442 lsa, _ := syscall.Getsockname(netfd.sysfd) 443 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 444 return netfd, nil 445 } 446 447 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 448 // If the kernel doesn't support it, this is set to 0. 449 var tryDupCloexec = int32(1) 450 451 func dupCloseOnExec(fd int) (newfd int, err error) { 452 if atomic.LoadInt32(&tryDupCloexec) == 1 { 453 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 454 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 455 // On OS X 10.6 and below (but we only support 456 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 457 // and fcntl there falls back (undocumented) 458 // to doing an ioctl instead, returning EBADF 459 // in this case because fd is not of the 460 // expected device fd type. Treat it as 461 // EINVAL instead, so we fall back to the 462 // normal dup path. 463 // TODO: only do this on 10.6 if we can detect 10.6 464 // cheaply. 465 e1 = syscall.EINVAL 466 } 467 switch e1 { 468 case 0: 469 return int(r0), nil 470 case syscall.EINVAL: 471 // Old kernel. Fall back to the portable way 472 // from now on. 473 atomic.StoreInt32(&tryDupCloexec, 0) 474 default: 475 return -1, os.NewSyscallError("fcntl", e1) 476 } 477 } 478 return dupCloseOnExecOld(fd) 479 } 480 481 // dupCloseOnExecUnixOld is the traditional way to dup an fd and 482 // set its O_CLOEXEC bit, using two system calls. 483 func dupCloseOnExecOld(fd int) (newfd int, err error) { 484 syscall.ForkLock.RLock() 485 defer syscall.ForkLock.RUnlock() 486 newfd, err = syscall.Dup(fd) 487 if err != nil { 488 return -1, os.NewSyscallError("dup", err) 489 } 490 syscall.CloseOnExec(newfd) 491 return 492 } 493 494 func (fd *netFD) dup() (f *os.File, err error) { 495 ns, err := dupCloseOnExec(fd.sysfd) 496 if err != nil { 497 return nil, err 498 } 499 500 // We want blocking mode for the new fd, hence the double negative. 501 // This also puts the old fd into blocking mode, meaning that 502 // I/O will block the thread instead of letting us use the epoll server. 503 // Everything will still work, just with more threads. 504 if err = syscall.SetNonblock(ns, false); err != nil { 505 return nil, os.NewSyscallError("setnonblock", err) 506 } 507 508 return os.NewFile(uintptr(ns), fd.name()), nil 509 }