github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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 netbsd openbsd 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) 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 if err := fd.pd.PrepareWrite(); err != nil { 76 return err 77 } 78 for { 79 err := syscall.Connect(fd.sysfd, ra) 80 if err == nil || err == syscall.EISCONN { 81 break 82 } 83 if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR { 84 return err 85 } 86 if err = fd.pd.WaitWrite(); err != nil { 87 return err 88 } 89 } 90 return nil 91 } 92 93 func (fd *netFD) destroy() { 94 // Poller may want to unregister fd in readiness notification mechanism, 95 // so this must be executed before closesocket. 96 fd.pd.Close() 97 closesocket(fd.sysfd) 98 fd.sysfd = -1 99 runtime.SetFinalizer(fd, nil) 100 } 101 102 // Add a reference to this fd. 103 // Returns an error if the fd cannot be used. 104 func (fd *netFD) incref() error { 105 if !fd.fdmu.Incref() { 106 return errClosing 107 } 108 return nil 109 } 110 111 // Remove a reference to this FD and close if we've been asked to do so 112 // (and there are no references left). 113 func (fd *netFD) decref() { 114 if fd.fdmu.Decref() { 115 fd.destroy() 116 } 117 } 118 119 // Add a reference to this fd and lock for reading. 120 // Returns an error if the fd cannot be used. 121 func (fd *netFD) readLock() error { 122 if !fd.fdmu.RWLock(true) { 123 return errClosing 124 } 125 return nil 126 } 127 128 // Unlock for reading and remove a reference to this FD. 129 func (fd *netFD) readUnlock() { 130 if fd.fdmu.RWUnlock(true) { 131 fd.destroy() 132 } 133 } 134 135 // Add a reference to this fd and lock for writing. 136 // Returns an error if the fd cannot be used. 137 func (fd *netFD) writeLock() error { 138 if !fd.fdmu.RWLock(false) { 139 return errClosing 140 } 141 return nil 142 } 143 144 // Unlock for writing and remove a reference to this FD. 145 func (fd *netFD) writeUnlock() { 146 if fd.fdmu.RWUnlock(false) { 147 fd.destroy() 148 } 149 } 150 151 func (fd *netFD) Close() error { 152 fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict 153 if !fd.fdmu.IncrefAndClose() { 154 fd.pd.Unlock() 155 return errClosing 156 } 157 // Unblock any I/O. Once it all unblocks and returns, 158 // so that it cannot be referring to fd.sysfd anymore, 159 // the final decref will close fd.sysfd. This should happen 160 // fairly quickly, since all the I/O is non-blocking, and any 161 // attempts to block in the pollDesc will return errClosing. 162 doWakeup := fd.pd.Evict() 163 fd.pd.Unlock() 164 fd.decref() 165 if doWakeup { 166 fd.pd.Wakeup() 167 } 168 return nil 169 } 170 171 func (fd *netFD) shutdown(how int) error { 172 if err := fd.incref(); err != nil { 173 return err 174 } 175 defer fd.decref() 176 err := syscall.Shutdown(fd.sysfd, how) 177 if err != nil { 178 return &OpError{"shutdown", fd.net, fd.laddr, err} 179 } 180 return nil 181 } 182 183 func (fd *netFD) CloseRead() error { 184 return fd.shutdown(syscall.SHUT_RD) 185 } 186 187 func (fd *netFD) CloseWrite() error { 188 return fd.shutdown(syscall.SHUT_WR) 189 } 190 191 func (fd *netFD) Read(p []byte) (n int, err error) { 192 if err := fd.readLock(); err != nil { 193 return 0, err 194 } 195 defer fd.readUnlock() 196 if err := fd.pd.PrepareRead(); err != nil { 197 return 0, &OpError{"read", fd.net, fd.raddr, err} 198 } 199 for { 200 n, err = syscall.Read(int(fd.sysfd), p) 201 if err != nil { 202 n = 0 203 if err == syscall.EAGAIN { 204 if err = fd.pd.WaitRead(); err == nil { 205 continue 206 } 207 } 208 } 209 err = chkReadErr(n, err, fd) 210 break 211 } 212 if err != nil && err != io.EOF { 213 err = &OpError{"read", fd.net, fd.raddr, err} 214 } 215 return 216 } 217 218 func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) { 219 if err := fd.readLock(); err != nil { 220 return 0, nil, err 221 } 222 defer fd.readUnlock() 223 if err := fd.pd.PrepareRead(); err != nil { 224 return 0, nil, &OpError{"read", fd.net, fd.laddr, err} 225 } 226 for { 227 n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0) 228 if err != nil { 229 n = 0 230 if err == syscall.EAGAIN { 231 if err = fd.pd.WaitRead(); err == nil { 232 continue 233 } 234 } 235 } 236 err = chkReadErr(n, err, fd) 237 break 238 } 239 if err != nil && err != io.EOF { 240 err = &OpError{"read", fd.net, fd.laddr, err} 241 } 242 return 243 } 244 245 func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) { 246 if err := fd.readLock(); err != nil { 247 return 0, 0, 0, nil, err 248 } 249 defer fd.readUnlock() 250 if err := fd.pd.PrepareRead(); err != nil { 251 return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err} 252 } 253 for { 254 n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0) 255 if err != nil { 256 // TODO(dfc) should n and oobn be set to 0 257 if err == syscall.EAGAIN { 258 if err = fd.pd.WaitRead(); err == nil { 259 continue 260 } 261 } 262 } 263 err = chkReadErr(n, err, fd) 264 break 265 } 266 if err != nil && err != io.EOF { 267 err = &OpError{"read", fd.net, fd.laddr, err} 268 } 269 return 270 } 271 272 func chkReadErr(n int, err error, fd *netFD) error { 273 if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW { 274 return io.EOF 275 } 276 return err 277 } 278 279 func (fd *netFD) Write(p []byte) (nn int, err error) { 280 if err := fd.writeLock(); err != nil { 281 return 0, err 282 } 283 defer fd.writeUnlock() 284 if err := fd.pd.PrepareWrite(); err != nil { 285 return 0, &OpError{"write", fd.net, fd.raddr, err} 286 } 287 for { 288 var n int 289 n, err = syscall.Write(int(fd.sysfd), p[nn:]) 290 if n > 0 { 291 nn += n 292 } 293 if nn == len(p) { 294 break 295 } 296 if err == syscall.EAGAIN { 297 if err = fd.pd.WaitWrite(); err == nil { 298 continue 299 } 300 } 301 if err != nil { 302 n = 0 303 break 304 } 305 if n == 0 { 306 err = io.ErrUnexpectedEOF 307 break 308 } 309 } 310 if err != nil { 311 err = &OpError{"write", fd.net, fd.raddr, err} 312 } 313 return nn, err 314 } 315 316 func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) { 317 if err := fd.writeLock(); err != nil { 318 return 0, err 319 } 320 defer fd.writeUnlock() 321 if err := fd.pd.PrepareWrite(); err != nil { 322 return 0, &OpError{"write", fd.net, fd.raddr, err} 323 } 324 for { 325 err = syscall.Sendto(fd.sysfd, p, 0, sa) 326 if err == syscall.EAGAIN { 327 if err = fd.pd.WaitWrite(); err == nil { 328 continue 329 } 330 } 331 break 332 } 333 if err == nil { 334 n = len(p) 335 } else { 336 err = &OpError{"write", fd.net, fd.raddr, err} 337 } 338 return 339 } 340 341 func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) { 342 if err := fd.writeLock(); err != nil { 343 return 0, 0, err 344 } 345 defer fd.writeUnlock() 346 if err := fd.pd.PrepareWrite(); err != nil { 347 return 0, 0, &OpError{"write", fd.net, fd.raddr, err} 348 } 349 for { 350 err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0) 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 oobn = len(oob) 361 } else { 362 err = &OpError{"write", fd.net, fd.raddr, err} 363 } 364 return 365 } 366 367 func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) { 368 if err := fd.readLock(); err != nil { 369 return nil, err 370 } 371 defer fd.readUnlock() 372 373 var s int 374 var rsa syscall.Sockaddr 375 if err = fd.pd.PrepareRead(); err != nil { 376 return nil, &OpError{"accept", fd.net, fd.laddr, err} 377 } 378 for { 379 s, rsa, err = accept(fd.sysfd) 380 if err != nil { 381 if err == syscall.EAGAIN { 382 if err = fd.pd.WaitRead(); err == nil { 383 continue 384 } 385 } else if err == syscall.ECONNABORTED { 386 // This means that a socket on the listen queue was closed 387 // before we Accept()ed it; it's a silly error, so try again. 388 continue 389 } 390 return nil, &OpError{"accept", fd.net, fd.laddr, err} 391 } 392 break 393 } 394 395 if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil { 396 closesocket(s) 397 return nil, err 398 } 399 if err = netfd.init(); err != nil { 400 fd.Close() 401 return nil, err 402 } 403 lsa, _ := syscall.Getsockname(netfd.sysfd) 404 netfd.setAddr(toAddr(lsa), toAddr(rsa)) 405 return netfd, nil 406 } 407 408 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 409 // If the kernel doesn't support it, this is set to 0. 410 var tryDupCloexec = int32(1) 411 412 func dupCloseOnExec(fd int) (newfd int, err error) { 413 if atomic.LoadInt32(&tryDupCloexec) == 1 { 414 r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0) 415 if runtime.GOOS == "darwin" && e1 == syscall.EBADF { 416 // On OS X 10.6 and below (but we only support 417 // >= 10.6), F_DUPFD_CLOEXEC is unsupported 418 // and fcntl there falls back (undocumented) 419 // to doing an ioctl instead, returning EBADF 420 // in this case because fd is not of the 421 // expected device fd type. Treat it as 422 // EINVAL instead, so we fall back to the 423 // normal dup path. 424 // TODO: only do this on 10.6 if we can detect 10.6 425 // cheaply. 426 e1 = syscall.EINVAL 427 } 428 switch e1 { 429 case 0: 430 return int(r0), nil 431 case syscall.EINVAL: 432 // Old kernel. Fall back to the portable way 433 // from now on. 434 atomic.StoreInt32(&tryDupCloexec, 0) 435 default: 436 return -1, e1 437 } 438 } 439 return dupCloseOnExecOld(fd) 440 } 441 442 // dupCloseOnExecUnixOld is the traditional way to dup an fd and 443 // set its O_CLOEXEC bit, using two system calls. 444 func dupCloseOnExecOld(fd int) (newfd int, err error) { 445 syscall.ForkLock.RLock() 446 defer syscall.ForkLock.RUnlock() 447 newfd, err = syscall.Dup(fd) 448 if err != nil { 449 return -1, err 450 } 451 syscall.CloseOnExec(newfd) 452 return 453 } 454 455 func (fd *netFD) dup() (f *os.File, err error) { 456 ns, err := dupCloseOnExec(fd.sysfd) 457 if err != nil { 458 syscall.ForkLock.RUnlock() 459 return nil, &OpError{"dup", fd.net, fd.laddr, err} 460 } 461 462 // We want blocking mode for the new fd, hence the double negative. 463 // This also puts the old fd into blocking mode, meaning that 464 // I/O will block the thread instead of letting us use the epoll server. 465 // Everything will still work, just with more threads. 466 if err = syscall.SetNonblock(ns, false); err != nil { 467 return nil, &OpError{"setnonblock", fd.net, fd.laddr, err} 468 } 469 470 return os.NewFile(uintptr(ns), fd.name()), nil 471 } 472 473 func closesocket(s int) error { 474 return syscall.Close(s) 475 } 476 477 func skipRawSocketTests() (skip bool, skipmsg string, err error) { 478 if os.Getuid() != 0 { 479 return true, "skipping test; must be root", nil 480 } 481 return false, "", nil 482 }