github.com/letsencrypt/go@v0.0.0-20160714163537-4054769a31f6/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) 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 // Wait for the goroutine converting context.Done into a write timeout 105 // to exist, otherwise our caller might cancel the context and 106 // cause fd.setWriteDeadline(aLongTimeAgo) to cancel a successful dial. 107 done := make(chan bool) // must be unbuffered 108 defer func() { done <- true }() 109 go func() { 110 select { 111 case <-ctx.Done(): 112 // Force the runtime's poller to immediately give 113 // up waiting for writability. 114 fd.setWriteDeadline(aLongTimeAgo) 115 <-done 116 case <-done: 117 } 118 }() 119 120 for { 121 // Performing multiple connect system calls on a 122 // non-blocking socket under Unix variants does not 123 // necessarily result in earlier errors being 124 // returned. Instead, once runtime-integrated network 125 // poller tells us that the socket is ready, get the 126 // SO_ERROR socket option to see if the connection 127 // succeeded or failed. See issue 7474 for further 128 // details. 129 if err := fd.pd.waitWrite(); err != nil { 130 select { 131 case <-ctx.Done(): 132 return mapErr(ctx.Err()) 133 default: 134 } 135 return err 136 } 137 nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) 138 if err != nil { 139 return os.NewSyscallError("getsockopt", err) 140 } 141 switch err := syscall.Errno(nerr); err { 142 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: 143 case syscall.Errno(0), syscall.EISCONN: 144 if runtime.GOOS != "darwin" { 145 return nil 146 } 147 // See golang.org/issue/14548. 148 // On Darwin, multiple connect system calls on 149 // a non-blocking socket never harm SO_ERROR. 150 switch err := connectFunc(fd.sysfd, ra); err { 151 case nil, syscall.EISCONN: 152 return nil 153 } 154 default: 155 return os.NewSyscallError("getsockopt", err) 156 } 157 } 158 } 159 160 func (fd *netFD) destroy() { 161 // Poller may want to unregister fd in readiness notification mechanism, 162 // so this must be executed before closeFunc. 163 fd.pd.close() 164 closeFunc(fd.sysfd) 165 fd.sysfd = -1 166 runtime.SetFinalizer(fd, nil) 167 } 168 169 func (fd *netFD) Close() error { 170 if !fd.fdmu.increfAndClose() { 171 return errClosing 172 } 173 // Unblock any I/O. Once it all unblocks and returns, 174 // so that it cannot be referring to fd.sysfd anymore, 175 // the final decref will close fd.sysfd. This should happen 176 // fairly quickly, since all the I/O is non-blocking, and any 177 // attempts to block in the pollDesc will return errClosing. 178 fd.pd.evict() 179 fd.decref() 180 return nil 181 } 182 183 func (fd *netFD) shutdown(how int) error { 184 if err := fd.incref(); err != nil { 185 return err 186 } 187 defer fd.decref() 188 return os.NewSyscallError("shutdown", syscall.Shutdown(fd.sysfd, how)) 189 } 190 191 func (fd *netFD) closeRead() error { 192 return fd.shutdown(syscall.SHUT_RD) 193 } 194 195 func (fd *netFD) closeWrite() error { 196 return fd.shutdown(syscall.SHUT_WR) 197 } 198 199 func (fd *netFD) Read(p []byte) (n int, err error) { 200 if err := fd.readLock(); err != nil { 201 return 0, err 202 } 203 defer fd.readUnlock() 204 if len(p) == 0 { 205 // If the caller wanted a zero byte read, return immediately 206 // without trying. (But after acquiring the readLock.) Otherwise 207 // syscall.Read returns 0, nil and eofError turns that into 208 // io.EOF. 209 // TODO(bradfitz): make it wait for readability? (Issue 15735) 210 return 0, nil 211 } 212 if err := fd.pd.prepareRead(); err != nil { 213 return 0, err 214 } 215 for { 216 n, err = syscall.Read(fd.sysfd, p) 217 if err != nil { 218 n = 0 219 if err == syscall.EAGAIN { 220 if err = fd.pd.waitRead(); err == nil { 221 continue 222 } 223 } 224 } 225 err = fd.eofError(n, err) 226 break 227 } 228 if _, ok := err.(syscall.Errno); ok { 229 err = os.NewSyscallError("read", err) 230 } 231 return 232 } 233 234 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 235 if err := fd.readLock(); err != nil { 236 return 0, nil, err 237 } 238 defer fd.readUnlock() 239 if err := fd.pd.prepareRead(); err != nil { 240 return 0, nil, err 241 } 242 for { 243 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) 244 if err != nil { 245 n = 0 246 if err == syscall.EAGAIN { 247 if err = fd.pd.waitRead(); err == nil { 248 continue 249 } 250 } 251 } 252 err = fd.eofError(n, err) 253 break 254 } 255 if _, ok := err.(syscall.Errno); ok { 256 err = os.NewSyscallError("recvfrom", err) 257 } 258 return 259 } 260 261 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 262 if err := fd.readLock(); err != nil { 263 return 0, 0, 0, nil, err 264 } 265 defer fd.readUnlock() 266 if err := fd.pd.prepareRead(); err != nil { 267 return 0, 0, 0, nil, err 268 } 269 for { 270 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) 271 if err != nil { 272 // TODO(dfc) should n and oobn be set to 0 273 if err == syscall.EAGAIN { 274 if err = fd.pd.waitRead(); err == nil { 275 continue 276 } 277 } 278 } 279 err = fd.eofError(n, err) 280 break 281 } 282 if _, ok := err.(syscall.Errno); ok { 283 err = os.NewSyscallError("recvmsg", err) 284 } 285 return 286 } 287 288 func (fd *netFD) Write(p []byte) (nn int, err error) { 289 if err := fd.writeLock(); err != nil { 290 return 0, err 291 } 292 defer fd.writeUnlock() 293 if err := fd.pd.prepareWrite(); err != nil { 294 return 0, err 295 } 296 for { 297 var n int 298 n, err = syscall.Write(fd.sysfd, p[nn:]) 299 if n > 0 { 300 nn += n 301 } 302 if nn == len(p) { 303 break 304 } 305 if err == syscall.EAGAIN { 306 if err = fd.pd.waitWrite(); err == nil { 307 continue 308 } 309 } 310 if err != nil { 311 break 312 } 313 if n == 0 { 314 err = io.ErrUnexpectedEOF 315 break 316 } 317 } 318 if _, ok := err.(syscall.Errno); ok { 319 err = os.NewSyscallError("write", err) 320 } 321 return nn, err 322 } 323 324 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 325 if err := fd.writeLock(); err != nil { 326 return 0, err 327 } 328 defer fd.writeUnlock() 329 if err := fd.pd.prepareWrite(); err != nil { 330 return 0, err 331 } 332 for { 333 err = syscall.Sendto(fd.sysfd, p, 0, sa) 334 if err == syscall.EAGAIN { 335 if err = fd.pd.waitWrite(); err == nil { 336 continue 337 } 338 } 339 break 340 } 341 if err == nil { 342 n = len(p) 343 } 344 if _, ok := err.(syscall.Errno); ok { 345 err = os.NewSyscallError("sendto", err) 346 } 347 return 348 } 349 350 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 351 if err := fd.writeLock(); err != nil { 352 return 0, 0, err 353 } 354 defer fd.writeUnlock() 355 if err := fd.pd.prepareWrite(); err != nil { 356 return 0, 0, err 357 } 358 for { 359 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) 360 if err == syscall.EAGAIN { 361 if err = fd.pd.waitWrite(); err == nil { 362 continue 363 } 364 } 365 break 366 } 367 if err == nil { 368 oobn = len(oob) 369 } 370 if _, ok := err.(syscall.Errno); ok { 371 err = os.NewSyscallError("sendmsg", err) 372 } 373 return 374 } 375 376 func (fd *netFD) accept() (netfd *netFD, err error) { 377 if err := fd.readLock(); err != nil { 378 return nil, err 379 } 380 defer fd.readUnlock() 381 382 var s int 383 var rsa syscall.Sockaddr 384 if err = fd.pd.prepareRead(); err != nil { 385 return nil, err 386 } 387 for { 388 s, rsa, err = accept(fd.sysfd) 389 if err != nil { 390 nerr, ok := err.(*os.SyscallError) 391 if !ok { 392 return nil, err 393 } 394 switch nerr.Err { 395 case syscall.EAGAIN: 396 if err = fd.pd.waitRead(); err == nil { 397 continue 398 } 399 case syscall.ECONNABORTED: 400 // This means that a socket on the 401 // listen queue was closed before we 402 // Accept()ed it; it's a silly error, 403 // so try again. 404 continue 405 } 406 return nil, err 407 } 408 break 409 } 410 411 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 412 closeFunc(s) 413 return nil, err 414 } 415 if err = netfd.init(); err != nil { 416 fd.Close() 417 return nil, err 418 } 419 lsa, _ := syscall.Getsockname(netfd.sysfd) 420 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 421 return netfd, nil 422 } 423 424 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 425 // If the kernel doesn't support it, this is set to 0. 426 var tryDupCloexec = int32(1) 427 428 func dupCloseOnExec(fd int) (newfd int, err error) { 429 if atomic.LoadInt32(&tryDupCloexec) == 1 { 430 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 431 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 432 // On OS X 10.6 and below (but we only support 433 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 434 // and fcntl there falls back (undocumented) 435 // to doing an ioctl instead, returning EBADF 436 // in this case because fd is not of the 437 // expected device fd type. Treat it as 438 // EINVAL instead, so we fall back to the 439 // normal dup path. 440 // TODO: only do this on 10.6 if we can detect 10.6 441 // cheaply. 442 e1 = syscall.EINVAL 443 } 444 switch e1 { 445 case 0: 446 return int(r0), nil 447 case syscall.EINVAL: 448 // Old kernel. Fall back to the portable way 449 // from now on. 450 atomic.StoreInt32(&tryDupCloexec, 0) 451 default: 452 return -1, os.NewSyscallError("fcntl", e1) 453 } 454 } 455 return dupCloseOnExecOld(fd) 456 } 457 458 // dupCloseOnExecUnixOld is the traditional way to dup an fd and 459 // set its O_CLOEXEC bit, using two system calls. 460 func dupCloseOnExecOld(fd int) (newfd int, err error) { 461 syscall.ForkLock.RLock() 462 defer syscall.ForkLock.RUnlock() 463 newfd, err = syscall.Dup(fd) 464 if err != nil { 465 return -1, os.NewSyscallError("dup", err) 466 } 467 syscall.CloseOnExec(newfd) 468 return 469 } 470 471 func (fd *netFD) dup() (f *os.File, err error) { 472 ns, err := dupCloseOnExec(fd.sysfd) 473 if err != nil { 474 return nil, err 475 } 476 477 // We want blocking mode for the new fd, hence the double negative. 478 // This also puts the old fd into blocking mode, meaning that 479 // I/O will block the thread instead of letting us use the epoll server. 480 // Everything will still work, just with more threads. 481 if err = syscall.SetNonblock(ns, false); err != nil { 482 return nil, os.NewSyscallError("setnonblock", err) 483 } 484 485 return os.NewFile(uintptr(ns), fd.name()), nil 486 }