rsc.io/go@v0.0.0-20150416155037-e040fd465409/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 "io" 11 "os" 12 "runtime" 13 "sync/atomic" 14 "syscall" 15 "time" 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 dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) { 40 return dialer(deadline) 41 } 42 43 func newFD(sysfd, family, sotype int, net string) (*netFD, error) { 44 return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, nil 45 } 46 47 func (fd *netFD) init() error { 48 if err := fd.pd.Init(fd); err != nil { 49 return err 50 } 51 return nil 52 } 53 54 func (fd *netFD) setAddr(laddr, raddr Addr) { 55 fd.laddr = laddr 56 fd.raddr = raddr 57 runtime.SetFinalizer(fd, (*netFD).Close) 58 } 59 60 func (fd *netFD) name() string { 61 var ls, rs string 62 if fd.laddr != nil { 63 ls = fd.laddr.String() 64 } 65 if fd.raddr != nil { 66 rs = fd.raddr.String() 67 } 68 return fd.net + ":" + ls + "->" + rs 69 } 70 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 := connectFunc(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()) { 79 return errTimeout 80 } 81 if err := fd.init(); err != nil { 82 return err 83 } 84 return nil 85 case syscall.EINVAL: 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" { 92 return nil 93 } 94 fallthrough 95 default: 96 return err 97 } 98 if err := fd.init(); err != nil { 99 return err 100 } 101 if !deadline.IsZero() { 102 fd.setWriteDeadline(deadline) 103 defer fd.setWriteDeadline(noDeadline) 104 } 105 for { 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 113 // details. 114 if err := fd.pd.WaitWrite(); err != nil { 115 return err 116 } 117 nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR) 118 if err != nil { 119 return err 120 } 121 switch err := syscall.Errno(nerr); err { 122 case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR: 123 case syscall.Errno(0), syscall.EISCONN: 124 return nil 125 default: 126 return err 127 } 128 } 129 } 130 131 func (fd *netFD) destroy() { 132 // Poller may want to unregister fd in readiness notification mechanism, 133 // so this must be executed before closeFunc. 134 fd.pd.Close() 135 closeFunc(fd.sysfd) 136 fd.sysfd = -1 137 runtime.SetFinalizer(fd, nil) 138 } 139 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() { 144 return errClosing 145 } 146 return nil 147 } 148 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() { 153 fd.destroy() 154 } 155 } 156 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) { 161 return errClosing 162 } 163 return nil 164 } 165 166 // Unlock for reading and remove a reference to this FD. 167 func (fd *netFD) readUnlock() { 168 if fd.fdmu.RWUnlock(true) { 169 fd.destroy() 170 } 171 } 172 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) { 177 return errClosing 178 } 179 return nil 180 } 181 182 // Unlock for writing and remove a reference to this FD. 183 func (fd *netFD) writeUnlock() { 184 if fd.fdmu.RWUnlock(false) { 185 fd.destroy() 186 } 187 } 188 189 func (fd *netFD) Close() error { 190 if !fd.fdmu.IncrefAndClose() { 191 return errClosing 192 } 193 // Unblock any I/O. Once it all unblocks and returns, 194 // so that it cannot be referring to fd.sysfd anymore, 195 // the final decref will close fd.sysfd. This should happen 196 // fairly quickly, since all the I/O is non-blocking, and any 197 // attempts to block in the pollDesc will return errClosing. 198 fd.pd.Evict() 199 fd.decref() 200 return nil 201 } 202 203 func (fd *netFD) shutdown(how int) error { 204 if err := fd.incref(); err != nil { 205 return err 206 } 207 defer fd.decref() 208 err := syscall.Shutdown(fd.sysfd, how) 209 if err != nil { 210 return &OpError{"shutdown", fd.net, fd.laddr, err} 211 } 212 return nil 213 } 214 215 func (fd *netFD) closeRead() error { 216 return fd.shutdown(syscall.SHUT_RD) 217 } 218 219 func (fd *netFD) closeWrite() error { 220 return fd.shutdown(syscall.SHUT_WR) 221 } 222 223 func (fd *netFD) Read(p []byte) (n int, err error) { 224 if err := fd.readLock(); err != nil { 225 return 0, err 226 } 227 defer fd.readUnlock() 228 if err := fd.pd.PrepareRead(); err != nil { 229 return 0, &OpError{"read", fd.net, fd.raddr, err} 230 } 231 for { 232 n, err = syscall.Read(int(fd.sysfd), p) 233 if err != nil { 234 n = 0 235 if err == syscall.EAGAIN { 236 if err = fd.pd.WaitRead(); err == nil { 237 continue 238 } 239 } 240 } 241 err = fd.eofError(n, err) 242 break 243 } 244 if err != nil && err != io.EOF { 245 err = &OpError{"read", fd.net, fd.raddr, err} 246 } 247 return 248 } 249 250 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 251 if err := fd.readLock(); err != nil { 252 return 0, nil, err 253 } 254 defer fd.readUnlock() 255 if err := fd.pd.PrepareRead(); err != nil { 256 return 0, nil, &OpError{"read", fd.net, fd.laddr, err} 257 } 258 for { 259 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) 260 if err != nil { 261 n = 0 262 if err == syscall.EAGAIN { 263 if err = fd.pd.WaitRead(); err == nil { 264 continue 265 } 266 } 267 } 268 err = fd.eofError(n, err) 269 break 270 } 271 if err != nil && err != io.EOF { 272 err = &OpError{"read", fd.net, fd.laddr, err} 273 } 274 return 275 } 276 277 func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 278 if err := fd.readLock(); err != nil { 279 return 0, 0, 0, nil, err 280 } 281 defer fd.readUnlock() 282 if err := fd.pd.PrepareRead(); err != nil { 283 return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err} 284 } 285 for { 286 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) 287 if err != nil { 288 // TODO(dfc) should n and oobn be set to 0 289 if err == syscall.EAGAIN { 290 if err = fd.pd.WaitRead(); err == nil { 291 continue 292 } 293 } 294 } 295 err = fd.eofError(n, err) 296 break 297 } 298 if err != nil && err != io.EOF { 299 err = &OpError{"read", fd.net, fd.laddr, err} 300 } 301 return 302 } 303 304 func (fd *netFD) Write(p []byte) (nn int, err error) { 305 if err := fd.writeLock(); err != nil { 306 return 0, err 307 } 308 defer fd.writeUnlock() 309 if err := fd.pd.PrepareWrite(); err != nil { 310 return 0, &OpError{"write", fd.net, fd.raddr, err} 311 } 312 for { 313 var n int 314 n, err = syscall.Write(int(fd.sysfd), p[nn:]) 315 if n > 0 { 316 nn += n 317 } 318 if nn == len(p) { 319 break 320 } 321 if err == syscall.EAGAIN { 322 if err = fd.pd.WaitWrite(); err == nil { 323 continue 324 } 325 } 326 if err != nil { 327 n = 0 328 break 329 } 330 if n == 0 { 331 err = io.ErrUnexpectedEOF 332 break 333 } 334 } 335 if err != nil { 336 err = &OpError{"write", fd.net, fd.raddr, err} 337 } 338 return nn, err 339 } 340 341 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 342 if err := fd.writeLock(); err != nil { 343 return 0, err 344 } 345 defer fd.writeUnlock() 346 if err := fd.pd.PrepareWrite(); err != nil { 347 return 0, &OpError{"write", fd.net, fd.raddr, err} 348 } 349 for { 350 err = syscall.Sendto(fd.sysfd, p, 0, sa) 351 if err == syscall.EAGAIN { 352 if err = fd.pd.WaitWrite(); err == nil { 353 continue 354 } 355 } 356 break 357 } 358 if err == nil { 359 n = len(p) 360 } else { 361 err = &OpError{"write", fd.net, fd.raddr, err} 362 } 363 return 364 } 365 366 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 367 if err := fd.writeLock(); err != nil { 368 return 0, 0, err 369 } 370 defer fd.writeUnlock() 371 if err := fd.pd.PrepareWrite(); err != nil { 372 return 0, 0, &OpError{"write", fd.net, fd.raddr, err} 373 } 374 for { 375 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) 376 if err == syscall.EAGAIN { 377 if err = fd.pd.WaitWrite(); err == nil { 378 continue 379 } 380 } 381 break 382 } 383 if err == nil { 384 oobn = len(oob) 385 } else { 386 err = &OpError{"write", fd.net, fd.raddr, err} 387 } 388 return 389 } 390 391 func (fd *netFD) accept() (netfd *netFD, err error) { 392 if err := fd.readLock(); err != nil { 393 return nil, err 394 } 395 defer fd.readUnlock() 396 397 var s int 398 var rsa syscall.Sockaddr 399 if err = fd.pd.PrepareRead(); err != nil { 400 return nil, &OpError{"accept", fd.net, fd.laddr, err} 401 } 402 for { 403 s, rsa, err = accept(fd.sysfd) 404 if err != nil { 405 if err == syscall.EAGAIN { 406 if err = fd.pd.WaitRead(); err == nil { 407 continue 408 } 409 } else if err == syscall.ECONNABORTED { 410 // This means that a socket on the listen queue was closed 411 // before we Accept()ed it; it's a silly error, so try again. 412 continue 413 } 414 return nil, &OpError{"accept", fd.net, fd.laddr, err} 415 } 416 break 417 } 418 419 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 420 closeFunc(s) 421 return nil, err 422 } 423 if err = netfd.init(); err != nil { 424 fd.Close() 425 return nil, err 426 } 427 lsa, _ := syscall.Getsockname(netfd.sysfd) 428 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 429 return netfd, nil 430 } 431 432 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 433 // If the kernel doesn't support it, this is set to 0. 434 var tryDupCloexec = int32(1) 435 436 func dupCloseOnExec(fd int) (newfd int, err error) { 437 if atomic.LoadInt32(&tryDupCloexec) == 1 { 438 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 439 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 440 // On OS X 10.6 and below (but we only support 441 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 442 // and fcntl there falls back (undocumented) 443 // to doing an ioctl instead, returning EBADF 444 // in this case because fd is not of the 445 // expected device fd type. Treat it as 446 // EINVAL instead, so we fall back to the 447 // normal dup path. 448 // TODO: only do this on 10.6 if we can detect 10.6 449 // cheaply. 450 e1 = syscall.EINVAL 451 } 452 switch e1 { 453 case 0: 454 return int(r0), nil 455 case syscall.EINVAL: 456 // Old kernel. Fall back to the portable way 457 // from now on. 458 atomic.StoreInt32(&tryDupCloexec, 0) 459 default: 460 return -1, e1 461 } 462 } 463 return dupCloseOnExecOld(fd) 464 } 465 466 // dupCloseOnExecUnixOld is the traditional way to dup an fd and 467 // set its O_CLOEXEC bit, using two system calls. 468 func dupCloseOnExecOld(fd int) (newfd int, err error) { 469 syscall.ForkLock.RLock() 470 defer syscall.ForkLock.RUnlock() 471 newfd, err = syscall.Dup(fd) 472 if err != nil { 473 return -1, err 474 } 475 syscall.CloseOnExec(newfd) 476 return 477 } 478 479 func (fd *netFD) dup() (f *os.File, err error) { 480 ns, err := dupCloseOnExec(fd.sysfd) 481 if err != nil { 482 return nil, &OpError{"dup", fd.net, fd.laddr, err} 483 } 484 485 // We want blocking mode for the new fd, hence the double negative. 486 // This also puts the old fd into blocking mode, meaning that 487 // I/O will block the thread instead of letting us use the epoll server. 488 // Everything will still work, just with more threads. 489 if err = syscall.SetNonblock(ns, false); err != nil { 490 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} 491 } 492 493 return os.NewFile(uintptr(ns), fd.name()), nil 494 }