github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/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 = chkReadErr(n, err, fd) 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 = chkReadErr(n, err, fd) 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 = chkReadErr(n, err, fd) 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 chkReadErr(n int, err error, fd *netFD) error { 311 if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW { 312 return io.EOF 313 } 314 return err 315 } 316 317 func (fd *netFD) Write(p []byte) (nn int, err error) { 318 if err := fd.writeLock(); err != nil { 319 return 0, err 320 } 321 defer fd.writeUnlock() 322 if err := fd.pd.PrepareWrite(); err != nil { 323 return 0, &OpError{"write", fd.net, fd.raddr, err} 324 } 325 for { 326 var n int 327 n, err = syscall.Write(int(fd.sysfd), p[nn:]) 328 if n > 0 { 329 nn += n 330 } 331 if nn == len(p) { 332 break 333 } 334 if err == syscall.EAGAIN { 335 if err = fd.pd.WaitWrite(); err == nil { 336 continue 337 } 338 } 339 if err != nil { 340 n = 0 341 break 342 } 343 if n == 0 { 344 err = io.ErrUnexpectedEOF 345 break 346 } 347 } 348 if err != nil { 349 err = &OpError{"write", fd.net, fd.raddr, err} 350 } 351 return nn, err 352 } 353 354 func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 355 if err := fd.writeLock(); err != nil { 356 return 0, err 357 } 358 defer fd.writeUnlock() 359 if err := fd.pd.PrepareWrite(); err != nil { 360 return 0, &OpError{"write", fd.net, fd.raddr, err} 361 } 362 for { 363 err = syscall.Sendto(fd.sysfd, p, 0, sa) 364 if err == syscall.EAGAIN { 365 if err = fd.pd.WaitWrite(); err == nil { 366 continue 367 } 368 } 369 break 370 } 371 if err == nil { 372 n = len(p) 373 } else { 374 err = &OpError{"write", fd.net, fd.raddr, err} 375 } 376 return 377 } 378 379 func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 380 if err := fd.writeLock(); err != nil { 381 return 0, 0, err 382 } 383 defer fd.writeUnlock() 384 if err := fd.pd.PrepareWrite(); err != nil { 385 return 0, 0, &OpError{"write", fd.net, fd.raddr, err} 386 } 387 for { 388 n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0) 389 if err == syscall.EAGAIN { 390 if err = fd.pd.WaitWrite(); err == nil { 391 continue 392 } 393 } 394 break 395 } 396 if err == nil { 397 oobn = len(oob) 398 } else { 399 err = &OpError{"write", fd.net, fd.raddr, err} 400 } 401 return 402 } 403 404 func (fd *netFD) accept() (netfd *netFD, err error) { 405 if err := fd.readLock(); err != nil { 406 return nil, err 407 } 408 defer fd.readUnlock() 409 410 var s int 411 var rsa syscall.Sockaddr 412 if err = fd.pd.PrepareRead(); err != nil { 413 return nil, &OpError{"accept", fd.net, fd.laddr, err} 414 } 415 for { 416 s, rsa, err = accept(fd.sysfd) 417 if err != nil { 418 if err == syscall.EAGAIN { 419 if err = fd.pd.WaitRead(); err == nil { 420 continue 421 } 422 } else if err == syscall.ECONNABORTED { 423 // This means that a socket on the listen queue was closed 424 // before we Accept()ed it; it's a silly error, so try again. 425 continue 426 } 427 return nil, &OpError{"accept", fd.net, fd.laddr, err} 428 } 429 break 430 } 431 432 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 433 closesocket(s) 434 return nil, err 435 } 436 if err = netfd.init(); err != nil { 437 fd.Close() 438 return nil, err 439 } 440 lsa, _ := syscall.Getsockname(netfd.sysfd) 441 netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa)) 442 return netfd, nil 443 } 444 445 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 446 // If the kernel doesn't support it, this is set to 0. 447 var tryDupCloexec = int32(1) 448 449 func dupCloseOnExec(fd int) (newfd int, err error) { 450 if atomic.LoadInt32(&tryDupCloexec) == 1 { 451 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 452 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 453 // On OS X 10.6 and below (but we only support 454 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 455 // and fcntl there falls back (undocumented) 456 // to doing an ioctl instead, returning EBADF 457 // in this case because fd is not of the 458 // expected device fd type. Treat it as 459 // EINVAL instead, so we fall back to the 460 // normal dup path. 461 // TODO: only do this on 10.6 if we can detect 10.6 462 // cheaply. 463 e1 = syscall.EINVAL 464 } 465 switch e1 { 466 case 0: 467 return int(r0), nil 468 case syscall.EINVAL: 469 // Old kernel. Fall back to the portable way 470 // from now on. 471 atomic.StoreInt32(&tryDupCloexec, 0) 472 default: 473 return -1, e1 474 } 475 } 476 return dupCloseOnExecOld(fd) 477 } 478 479 // dupCloseOnExecUnixOld is the traditional way to dup an fd and 480 // set its O_CLOEXEC bit, using two system calls. 481 func dupCloseOnExecOld(fd int) (newfd int, err error) { 482 syscall.ForkLock.RLock() 483 defer syscall.ForkLock.RUnlock() 484 newfd, err = syscall.Dup(fd) 485 if err != nil { 486 return -1, err 487 } 488 syscall.CloseOnExec(newfd) 489 return 490 } 491 492 func (fd *netFD) dup() (f *os.File, err error) { 493 ns, err := dupCloseOnExec(fd.sysfd) 494 if err != nil { 495 return nil, &OpError{"dup", fd.net, fd.laddr, err} 496 } 497 498 // We want blocking mode for the new fd, hence the double negative. 499 // This also puts the old fd into blocking mode, meaning that 500 // I/O will block the thread instead of letting us use the epoll server. 501 // Everything will still work, just with more threads. 502 if err = syscall.SetNonblock(ns, false); err != nil { 503 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} 504 } 505 506 return os.NewFile(uintptr(ns), fd.name()), nil 507 } 508 509 func closesocket(s int) error { 510 return syscall.Close(s) 511 } 512 513 func skipRawSocketTests() (skip bool, skipmsg string, err error) { 514 if os.Getuid() != 0 { 515 return true, "skipping test; must be root", nil 516 } 517 return false, "", nil 518 }