github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/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 := 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()) { 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 := syscall.GetsockoptInt(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 closesocket. 134 fd.pd.Close() 135 closesocket(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 fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict 191 if !fd.fdmu.IncrefAndClose() { 192 fd.pd.Unlock() 193 return errClosing 194 } 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() 201 fd.pd.Unlock() 202 fd.decref() 203 if doWakeup { 204 fd.pd.Wakeup() 205 } 206 return nil 207 } 208 209 func (fd *netFD) shutdown(how int) error { 210 if err := fd.incref(); err != nil { 211 return err 212 } 213 defer fd.decref() 214 err := syscall.Shutdown(fd.sysfd, how) 215 if err != nil { 216 return &OpError{"shutdown", fd.net, fd.laddr, err} 217 } 218 return nil 219 } 220 221 func (fd *netFD) closeRead() error { 222 return fd.shutdown(syscall.SHUT_RD) 223 } 224 225 func (fd *netFD) closeWrite() error { 226 return fd.shutdown(syscall.SHUT_WR) 227 } 228 229 func (fd *netFD) Read(p []byte) (n int, err error) { 230 if err := fd.readLock(); err != nil { 231 return 0, err 232 } 233 defer fd.readUnlock() 234 if err := fd.pd.PrepareRead(); err != nil { 235 return 0, &OpError{"read", fd.net, fd.raddr, err} 236 } 237 for { 238 n, err = syscall.Read(int(fd.sysfd), p) 239 if err != nil { 240 n = 0 241 if err == syscall.EAGAIN { 242 if err = fd.pd.WaitRead(); err == nil { 243 continue 244 } 245 } 246 } 247 err = fd.eofError(n, err) 248 break 249 } 250 if err != nil && err != io.EOF { 251 err = &OpError{"read", fd.net, fd.raddr, err} 252 } 253 return 254 } 255 256 func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 257 if err := fd.readLock(); err != nil { 258 return 0, nil, err 259 } 260 defer fd.readUnlock() 261 if err := fd.pd.PrepareRead(); err != nil { 262 return 0, nil, &OpError{"read", fd.net, fd.laddr, err} 263 } 264 for { 265 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) 266 if err != nil { 267 n = 0 268 if err == syscall.EAGAIN { 269 if err = fd.pd.WaitRead(); err == nil { 270 continue 271 } 272 } 273 } 274 err = fd.eofError(n, err) 275 break 276 } 277 if err != nil && err != io.EOF { 278 err = &OpError{"read", fd.net, fd.laddr, err} 279 } 280 return 281 } 282 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 286 } 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} 290 } 291 for { 292 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) 293 if err != nil { 294 // TODO(dfc) should n and oobn be set to 0 295 if err == syscall.EAGAIN { 296 if err = fd.pd.WaitRead(); err == nil { 297 continue 298 } 299 } 300 } 301 err = fd.eofError(n, err) 302 break 303 } 304 if err != nil && err != io.EOF { 305 err = &OpError{"read", fd.net, fd.laddr, err} 306 } 307 return 308 } 309 310 func (fd *netFD) Write(p []byte) (nn int, err error) { 311 if err := fd.writeLock(); err != nil { 312 return 0, err 313 } 314 defer fd.writeUnlock() 315 if err := fd.pd.PrepareWrite(); err != nil { 316 return 0, &OpError{"write", fd.net, fd.raddr, err} 317 } 318 for { 319 var n int 320 n, err = syscall.Write(int(fd.sysfd), p[nn:]) 321 if n > 0 { 322 nn += n 323 } 324 if nn == len(p) { 325 break 326 } 327 if err == syscall.EAGAIN { 328 if err = fd.pd.WaitWrite(); err == nil { 329 continue 330 } 331 } 332 if err != nil { 333 n = 0 334 break 335 } 336 if n == 0 { 337 err = io.ErrUnexpectedEOF 338 break 339 } 340 } 341 if err != nil { 342 err = &OpError{"write", fd.net, fd.raddr, 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, &OpError{"write", fd.net, fd.raddr, 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 } else { 367 err = &OpError{"write", fd.net, fd.raddr, err} 368 } 369 return 370 } 371 372 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 373 if err := fd.writeLock(); err != nil { 374 return 0, 0, err 375 } 376 defer fd.writeUnlock() 377 if err := fd.pd.PrepareWrite(); err != nil { 378 return 0, 0, &OpError{"write", fd.net, fd.raddr, err} 379 } 380 for { 381 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) 382 if err == syscall.EAGAIN { 383 if err = fd.pd.WaitWrite(); err == nil { 384 continue 385 } 386 } 387 break 388 } 389 if err == nil { 390 oobn = len(oob) 391 } else { 392 err = &OpError{"write", fd.net, fd.raddr, err} 393 } 394 return 395 } 396 397 func (fd *netFD) accept() (netfd *netFD, err error) { 398 if err := fd.readLock(); err != nil { 399 return nil, err 400 } 401 defer fd.readUnlock() 402 403 var s int 404 var rsa syscall.Sockaddr 405 if err = fd.pd.PrepareRead(); err != nil { 406 return nil, &OpError{"accept", fd.net, fd.laddr, err} 407 } 408 for { 409 s, rsa, err = accept(fd.sysfd) 410 if err != nil { 411 if err == syscall.EAGAIN { 412 if err = fd.pd.WaitRead(); err == nil { 413 continue 414 } 415 } else if err == syscall.ECONNABORTED { 416 // This means that a socket on the listen queue was closed 417 // before we Accept()ed it; it's a silly error, so try again. 418 continue 419 } 420 return nil, &OpError{"accept", fd.net, fd.laddr, err} 421 } 422 break 423 } 424 425 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 426 closesocket(s) 427 return nil, err 428 } 429 if err = netfd.init(); err != nil { 430 fd.Close() 431 return nil, err 432 } 433 lsa, _ := syscall.Getsockname(netfd.sysfd) 434 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 435 return netfd, nil 436 } 437 438 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 439 // If the kernel doesn't support it, this is set to 0. 440 var tryDupCloexec = int32(1) 441 442 func dupCloseOnExec(fd int) (newfd int, err error) { 443 if atomic.LoadInt32(&tryDupCloexec) == 1 { 444 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 445 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 446 // On OS X 10.6 and below (but we only support 447 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 448 // and fcntl there falls back (undocumented) 449 // to doing an ioctl instead, returning EBADF 450 // in this case because fd is not of the 451 // expected device fd type. Treat it as 452 // EINVAL instead, so we fall back to the 453 // normal dup path. 454 // TODO: only do this on 10.6 if we can detect 10.6 455 // cheaply. 456 e1 = syscall.EINVAL 457 } 458 switch e1 { 459 case 0: 460 return int(r0), nil 461 case syscall.EINVAL: 462 // Old kernel. Fall back to the portable way 463 // from now on. 464 atomic.StoreInt32(&tryDupCloexec, 0) 465 default: 466 return -1, e1 467 } 468 } 469 return dupCloseOnExecOld(fd) 470 } 471 472 // dupCloseOnExecUnixOld is the traditional way to dup an fd and 473 // set its O_CLOEXEC bit, using two system calls. 474 func dupCloseOnExecOld(fd int) (newfd int, err error) { 475 syscall.ForkLock.RLock() 476 defer syscall.ForkLock.RUnlock() 477 newfd, err = syscall.Dup(fd) 478 if err != nil { 479 return -1, err 480 } 481 syscall.CloseOnExec(newfd) 482 return 483 } 484 485 func (fd *netFD) dup() (f *os.File, err error) { 486 ns, err := dupCloseOnExec(fd.sysfd) 487 if err != nil { 488 return nil, &OpError{"dup", fd.net, fd.laddr, err} 489 } 490 491 // We want blocking mode for the new fd, hence the double negative. 492 // This also puts the old fd into blocking mode, meaning that 493 // I/O will block the thread instead of letting us use the epoll server. 494 // Everything will still work, just with more threads. 495 if err = syscall.SetNonblock(ns, false); err != nil { 496 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} 497 } 498 499 return os.NewFile(uintptr(ns), fd.name()), nil 500 } 501 502 func closesocket(s int) error { 503 return syscall.Close(s) 504 } 505 506 func skipRawSocketTests() (skip bool, skipmsg string, err error) { 507 if os.Getuid() != 0 { 508 return true, "skipping test; must be root", nil 509 } 510 return false, "", nil 511 }