github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/internal/poll/fd_windows.go (about) 1 // Copyright 2017 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 package poll 6 7 import ( 8 "errors" 9 "internal/race" 10 "io" 11 "runtime" 12 "sync" 13 "syscall" 14 "unicode/utf16" 15 "unicode/utf8" 16 "unsafe" 17 ) 18 19 var ( 20 initErr error 21 ioSync uint64 22 ) 23 24 // CancelIo Windows API cancels all outstanding IO for a particular 25 // socket on current thread. To overcome that limitation, we run 26 // special goroutine, locked to OS single thread, that both starts 27 // and cancels IO. It means, there are 2 unavoidable thread switches 28 // for every IO. 29 // Some newer versions of Windows has new CancelIoEx API, that does 30 // not have that limitation and can be used from any thread. This 31 // package uses CancelIoEx API, if present, otherwise it fallback 32 // to CancelIo. 33 34 var ( 35 canCancelIO bool // determines if CancelIoEx API is present 36 skipSyncNotif bool 37 hasLoadSetFileCompletionNotificationModes bool 38 ) 39 40 func init() { 41 var d syscall.WSAData 42 e := syscall.WSAStartup(uint32(0x202), &d) 43 if e != nil { 44 initErr = e 45 } 46 canCancelIO = syscall.LoadCancelIoEx() == nil 47 hasLoadSetFileCompletionNotificationModes = syscall.LoadSetFileCompletionNotificationModes() == nil 48 if hasLoadSetFileCompletionNotificationModes { 49 // It's not safe to use FILE_SKIP_COMPLETION_PORT_ON_SUCCESS if non IFS providers are installed: 50 // http://support.microsoft.com/kb/2568167 51 skipSyncNotif = true 52 protos := [2]int32{syscall.IPPROTO_TCP, 0} 53 var buf [32]syscall.WSAProtocolInfo 54 len := uint32(unsafe.Sizeof(buf)) 55 n, err := syscall.WSAEnumProtocols(&protos[0], &buf[0], &len) 56 if err != nil { 57 skipSyncNotif = false 58 } else { 59 for i := int32(0); i < n; i++ { 60 if buf[i].ServiceFlags1&syscall.XP1_IFS_HANDLES == 0 { 61 skipSyncNotif = false 62 break 63 } 64 } 65 } 66 } 67 } 68 69 // operation contains superset of data necessary to perform all async IO. 70 type operation struct { 71 // Used by IOCP interface, it must be first field 72 // of the struct, as our code rely on it. 73 o syscall.Overlapped 74 75 // fields used by runtime.netpoll 76 runtimeCtx uintptr 77 mode int32 78 errno int32 79 qty uint32 80 81 // fields used only by net package 82 fd *FD 83 errc chan error 84 buf syscall.WSABuf 85 sa syscall.Sockaddr 86 rsa *syscall.RawSockaddrAny 87 rsan int32 88 handle syscall.Handle 89 flags uint32 90 bufs []syscall.WSABuf 91 } 92 93 func (o *operation) InitBuf(buf []byte) { 94 o.buf.Len = uint32(len(buf)) 95 o.buf.Buf = nil 96 if len(buf) != 0 { 97 o.buf.Buf = &buf[0] 98 } 99 } 100 101 func (o *operation) InitBufs(buf *[][]byte) { 102 if o.bufs == nil { 103 o.bufs = make([]syscall.WSABuf, 0, len(*buf)) 104 } else { 105 o.bufs = o.bufs[:0] 106 } 107 for _, b := range *buf { 108 var p *byte 109 if len(b) > 0 { 110 p = &b[0] 111 } 112 o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: p}) 113 } 114 } 115 116 // ClearBufs clears all pointers to Buffers parameter captured 117 // by InitBufs, so it can be released by garbage collector. 118 func (o *operation) ClearBufs() { 119 for i := range o.bufs { 120 o.bufs[i].Buf = nil 121 } 122 o.bufs = o.bufs[:0] 123 } 124 125 // ioSrv executes net IO requests. 126 type ioSrv struct { 127 req chan ioSrvReq 128 } 129 130 type ioSrvReq struct { 131 o *operation 132 submit func(o *operation) error // if nil, cancel the operation 133 } 134 135 // ProcessRemoteIO will execute submit IO requests on behalf 136 // of other goroutines, all on a single os thread, so it can 137 // cancel them later. Results of all operations will be sent 138 // back to their requesters via channel supplied in request. 139 // It is used only when the CancelIoEx API is unavailable. 140 func (s *ioSrv) ProcessRemoteIO() { 141 runtime.LockOSThread() 142 defer runtime.UnlockOSThread() 143 for r := range s.req { 144 if r.submit != nil { 145 r.o.errc <- r.submit(r.o) 146 } else { 147 r.o.errc <- syscall.CancelIo(r.o.fd.Sysfd) 148 } 149 } 150 } 151 152 // ExecIO executes a single IO operation o. It submits and cancels 153 // IO in the current thread for systems where Windows CancelIoEx API 154 // is available. Alternatively, it passes the request onto 155 // runtime netpoll and waits for completion or cancels request. 156 func (s *ioSrv) ExecIO(o *operation, name string, submit func(o *operation) error) (int, error) { 157 fd := o.fd 158 // Notify runtime netpoll about starting IO. 159 err := fd.pd.prepare(int(o.mode)) 160 if err != nil { 161 return 0, err 162 } 163 // Start IO. 164 if canCancelIO { 165 err = submit(o) 166 } else { 167 // Send request to a special dedicated thread, 168 // so it can stop the IO with CancelIO later. 169 s.req <- ioSrvReq{o, submit} 170 err = <-o.errc 171 } 172 switch err { 173 case nil: 174 // IO completed immediately 175 if o.fd.skipSyncNotif { 176 // No completion message will follow, so return immediately. 177 return int(o.qty), nil 178 } 179 // Need to get our completion message anyway. 180 case syscall.ERROR_IO_PENDING: 181 // IO started, and we have to wait for its completion. 182 err = nil 183 default: 184 return 0, err 185 } 186 // Wait for our request to complete. 187 err = fd.pd.wait(int(o.mode)) 188 if err == nil { 189 // All is good. Extract our IO results and return. 190 if o.errno != 0 { 191 err = syscall.Errno(o.errno) 192 return 0, err 193 } 194 return int(o.qty), nil 195 } 196 // IO is interrupted by "close" or "timeout" 197 netpollErr := err 198 switch netpollErr { 199 case ErrClosing, ErrTimeout: 200 // will deal with those. 201 default: 202 panic("net: unexpected runtime.netpoll error: " + netpollErr.Error()) 203 } 204 // Cancel our request. 205 if canCancelIO { 206 err := syscall.CancelIoEx(fd.Sysfd, &o.o) 207 // Assuming ERROR_NOT_FOUND is returned, if IO is completed. 208 if err != nil && err != syscall.ERROR_NOT_FOUND { 209 // TODO(brainman): maybe do something else, but panic. 210 panic(err) 211 } 212 } else { 213 s.req <- ioSrvReq{o, nil} 214 <-o.errc 215 } 216 // Wait for cancelation to complete. 217 fd.pd.waitCanceled(int(o.mode)) 218 if o.errno != 0 { 219 err = syscall.Errno(o.errno) 220 if err == syscall.ERROR_OPERATION_ABORTED { // IO Canceled 221 err = netpollErr 222 } 223 return 0, err 224 } 225 // We issued a cancelation request. But, it seems, IO operation succeeded 226 // before the cancelation request run. We need to treat the IO operation as 227 // succeeded (the bytes are actually sent/recv from network). 228 return int(o.qty), nil 229 } 230 231 // Start helper goroutines. 232 var rsrv, wsrv *ioSrv 233 var onceStartServer sync.Once 234 235 func startServer() { 236 rsrv = new(ioSrv) 237 wsrv = new(ioSrv) 238 if !canCancelIO { 239 // Only CancelIo API is available. Lets start two special goroutines 240 // locked to an OS thread, that both starts and cancels IO. One will 241 // process read requests, while other will do writes. 242 rsrv.req = make(chan ioSrvReq) 243 go rsrv.ProcessRemoteIO() 244 wsrv.req = make(chan ioSrvReq) 245 go wsrv.ProcessRemoteIO() 246 } 247 } 248 249 // FD is a file descriptor. The net and os packages embed this type in 250 // a larger type representing a network connection or OS file. 251 type FD struct { 252 // Lock sysfd and serialize access to Read and Write methods. 253 fdmu fdMutex 254 255 // System file descriptor. Immutable until Close. 256 Sysfd syscall.Handle 257 258 // Read operation. 259 rop operation 260 // Write operation. 261 wop operation 262 263 // I/O poller. 264 pd pollDesc 265 266 // Used to implement pread/pwrite. 267 l sync.Mutex 268 269 // For console I/O. 270 isConsole bool 271 lastbits []byte // first few bytes of the last incomplete rune in last write 272 readuint16 []uint16 // buffer to hold uint16s obtained with ReadConsole 273 readbyte []byte // buffer to hold decoding of readuint16 from utf16 to utf8 274 readbyteOffset int // readbyte[readOffset:] is yet to be consumed with file.Read 275 276 skipSyncNotif bool 277 278 // Whether this is a streaming descriptor, as opposed to a 279 // packet-based descriptor like a UDP socket. 280 IsStream bool 281 282 // Whether a zero byte read indicates EOF. This is false for a 283 // message based socket connection. 284 ZeroReadIsEOF bool 285 286 // Whether this is a normal file. 287 isFile bool 288 289 // Whether this is a directory. 290 isDir bool 291 } 292 293 // Init initializes the FD. The Sysfd field should already be set. 294 // This can be called multiple times on a single FD. 295 // The net argument is a network name from the net package (e.g., "tcp"), 296 // or "file" or "console" or "dir". 297 func (fd *FD) Init(net string) (string, error) { 298 if initErr != nil { 299 return "", initErr 300 } 301 onceStartServer.Do(startServer) 302 303 switch net { 304 case "file": 305 fd.isFile = true 306 case "console": 307 fd.isConsole = true 308 case "dir": 309 fd.isDir = true 310 case "tcp", "tcp4", "tcp6": 311 case "udp", "udp4", "udp6": 312 case "ip", "ip4", "ip6": 313 case "unix", "unixgram", "unixpacket": 314 default: 315 return "", errors.New("internal error: unknown network type " + net) 316 } 317 318 if err := fd.pd.init(fd); err != nil { 319 return "", err 320 } 321 if hasLoadSetFileCompletionNotificationModes { 322 // We do not use events, so we can skip them always. 323 flags := uint8(syscall.FILE_SKIP_SET_EVENT_ON_HANDLE) 324 // It's not safe to skip completion notifications for UDP: 325 // http://blogs.technet.com/b/winserverperformance/archive/2008/06/26/designing-applications-for-high-performance-part-iii.aspx 326 if skipSyncNotif && (net == "tcp" || net == "file") { 327 flags |= syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS 328 } 329 err := syscall.SetFileCompletionNotificationModes(fd.Sysfd, flags) 330 if err == nil && flags&syscall.FILE_SKIP_COMPLETION_PORT_ON_SUCCESS != 0 { 331 fd.skipSyncNotif = true 332 } 333 } 334 // Disable SIO_UDP_CONNRESET behavior. 335 // http://support.microsoft.com/kb/263823 336 switch net { 337 case "udp", "udp4", "udp6": 338 ret := uint32(0) 339 flag := uint32(0) 340 size := uint32(unsafe.Sizeof(flag)) 341 err := syscall.WSAIoctl(fd.Sysfd, syscall.SIO_UDP_CONNRESET, (*byte)(unsafe.Pointer(&flag)), size, nil, 0, &ret, nil, 0) 342 if err != nil { 343 return "wsaioctl", err 344 } 345 } 346 fd.rop.mode = 'r' 347 fd.wop.mode = 'w' 348 fd.rop.fd = fd 349 fd.wop.fd = fd 350 fd.rop.runtimeCtx = fd.pd.runtimeCtx 351 fd.wop.runtimeCtx = fd.pd.runtimeCtx 352 if !canCancelIO { 353 fd.rop.errc = make(chan error) 354 fd.wop.errc = make(chan error) 355 } 356 return "", nil 357 } 358 359 func (fd *FD) destroy() error { 360 if fd.Sysfd == syscall.InvalidHandle { 361 return syscall.EINVAL 362 } 363 // Poller may want to unregister fd in readiness notification mechanism, 364 // so this must be executed before fd.CloseFunc. 365 fd.pd.close() 366 var err error 367 if fd.isFile || fd.isConsole { 368 err = syscall.CloseHandle(fd.Sysfd) 369 } else if fd.isDir { 370 err = syscall.FindClose(fd.Sysfd) 371 } else { 372 // The net package uses the CloseFunc variable for testing. 373 err = CloseFunc(fd.Sysfd) 374 } 375 fd.Sysfd = syscall.InvalidHandle 376 return err 377 } 378 379 func (fd *FD) Close() error { 380 if !fd.fdmu.increfAndClose() { 381 return ErrClosing 382 } 383 // unblock pending reader and writer 384 fd.pd.evict() 385 return fd.decref() 386 } 387 388 func (fd *FD) Shutdown(how int) error { 389 if err := fd.incref(); err != nil { 390 return err 391 } 392 defer fd.decref() 393 return syscall.Shutdown(fd.Sysfd, how) 394 } 395 396 func (fd *FD) Read(buf []byte) (int, error) { 397 if err := fd.readLock(); err != nil { 398 return 0, err 399 } 400 defer fd.readUnlock() 401 402 var n int 403 var err error 404 if fd.isFile || fd.isDir || fd.isConsole { 405 fd.l.Lock() 406 defer fd.l.Unlock() 407 if fd.isConsole { 408 n, err = fd.readConsole(buf) 409 } else { 410 n, err = syscall.Read(fd.Sysfd, buf) 411 } 412 if err != nil { 413 n = 0 414 } 415 } else { 416 o := &fd.rop 417 o.InitBuf(buf) 418 n, err = rsrv.ExecIO(o, "WSARecv", func(o *operation) error { 419 return syscall.WSARecv(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, &o.o, nil) 420 }) 421 if race.Enabled { 422 race.Acquire(unsafe.Pointer(&ioSync)) 423 } 424 } 425 if len(buf) != 0 { 426 err = fd.eofError(n, err) 427 } 428 return n, err 429 } 430 431 var ReadConsole = syscall.ReadConsole // changed for testing 432 433 // readConsole reads utf16 characters from console File, 434 // encodes them into utf8 and stores them in buffer b. 435 // It returns the number of utf8 bytes read and an error, if any. 436 func (fd *FD) readConsole(b []byte) (int, error) { 437 if len(b) == 0 { 438 return 0, nil 439 } 440 441 if fd.readuint16 == nil { 442 // Note: syscall.ReadConsole fails for very large buffers. 443 // The limit is somewhere around (but not exactly) 16384. 444 // Stay well below. 445 fd.readuint16 = make([]uint16, 0, 10000) 446 fd.readbyte = make([]byte, 0, 4*cap(fd.readuint16)) 447 } 448 449 for fd.readbyteOffset >= len(fd.readbyte) { 450 n := cap(fd.readuint16) - len(fd.readuint16) 451 if n > len(b) { 452 n = len(b) 453 } 454 var nw uint32 455 err := ReadConsole(fd.Sysfd, &fd.readuint16[:len(fd.readuint16)+1][len(fd.readuint16)], uint32(n), &nw, nil) 456 if err != nil { 457 return 0, err 458 } 459 uint16s := fd.readuint16[:len(fd.readuint16)+int(nw)] 460 fd.readuint16 = fd.readuint16[:0] 461 buf := fd.readbyte[:0] 462 for i := 0; i < len(uint16s); i++ { 463 r := rune(uint16s[i]) 464 if utf16.IsSurrogate(r) { 465 if i+1 == len(uint16s) { 466 if nw > 0 { 467 // Save half surrogate pair for next time. 468 fd.readuint16 = fd.readuint16[:1] 469 fd.readuint16[0] = uint16(r) 470 break 471 } 472 r = utf8.RuneError 473 } else { 474 r = utf16.DecodeRune(r, rune(uint16s[i+1])) 475 if r != utf8.RuneError { 476 i++ 477 } 478 } 479 } 480 n := utf8.EncodeRune(buf[len(buf):cap(buf)], r) 481 buf = buf[:len(buf)+n] 482 } 483 fd.readbyte = buf 484 fd.readbyteOffset = 0 485 if nw == 0 { 486 break 487 } 488 } 489 490 src := fd.readbyte[fd.readbyteOffset:] 491 var i int 492 for i = 0; i < len(src) && i < len(b); i++ { 493 x := src[i] 494 if x == 0x1A { // Ctrl-Z 495 if i == 0 { 496 fd.readbyteOffset++ 497 } 498 break 499 } 500 b[i] = x 501 } 502 fd.readbyteOffset += i 503 return i, nil 504 } 505 506 func (fd *FD) Pread(b []byte, off int64) (int, error) { 507 if err := fd.readLock(); err != nil { 508 return 0, err 509 } 510 defer fd.readUnlock() 511 512 fd.l.Lock() 513 defer fd.l.Unlock() 514 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 515 if e != nil { 516 return 0, e 517 } 518 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 519 o := syscall.Overlapped{ 520 OffsetHigh: uint32(off >> 32), 521 Offset: uint32(off), 522 } 523 var done uint32 524 e = syscall.ReadFile(fd.Sysfd, b, &done, &o) 525 if e != nil { 526 done = 0 527 if e == syscall.ERROR_HANDLE_EOF { 528 e = io.EOF 529 } 530 } 531 if len(b) != 0 { 532 e = fd.eofError(int(done), e) 533 } 534 return int(done), e 535 } 536 537 func (fd *FD) RecvFrom(buf []byte) (int, syscall.Sockaddr, error) { 538 if len(buf) == 0 { 539 return 0, nil, nil 540 } 541 if err := fd.readLock(); err != nil { 542 return 0, nil, err 543 } 544 defer fd.readUnlock() 545 o := &fd.rop 546 o.InitBuf(buf) 547 n, err := rsrv.ExecIO(o, "WSARecvFrom", func(o *operation) error { 548 if o.rsa == nil { 549 o.rsa = new(syscall.RawSockaddrAny) 550 } 551 o.rsan = int32(unsafe.Sizeof(*o.rsa)) 552 return syscall.WSARecvFrom(o.fd.Sysfd, &o.buf, 1, &o.qty, &o.flags, o.rsa, &o.rsan, &o.o, nil) 553 }) 554 err = fd.eofError(n, err) 555 if err != nil { 556 return n, nil, err 557 } 558 sa, _ := o.rsa.Sockaddr() 559 return n, sa, nil 560 } 561 562 func (fd *FD) Write(buf []byte) (int, error) { 563 if err := fd.writeLock(); err != nil { 564 return 0, err 565 } 566 defer fd.writeUnlock() 567 568 var n int 569 var err error 570 if fd.isFile || fd.isDir || fd.isConsole { 571 fd.l.Lock() 572 defer fd.l.Unlock() 573 if fd.isConsole { 574 n, err = fd.writeConsole(buf) 575 } else { 576 n, err = syscall.Write(fd.Sysfd, buf) 577 } 578 if err != nil { 579 n = 0 580 } 581 } else { 582 if race.Enabled { 583 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 584 } 585 o := &fd.wop 586 o.InitBuf(buf) 587 n, err = wsrv.ExecIO(o, "WSASend", func(o *operation) error { 588 return syscall.WSASend(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, &o.o, nil) 589 }) 590 } 591 return n, err 592 } 593 594 // writeConsole writes len(b) bytes to the console File. 595 // It returns the number of bytes written and an error, if any. 596 func (fd *FD) writeConsole(b []byte) (int, error) { 597 n := len(b) 598 runes := make([]rune, 0, 256) 599 if len(fd.lastbits) > 0 { 600 b = append(fd.lastbits, b...) 601 fd.lastbits = nil 602 603 } 604 for len(b) >= utf8.UTFMax || utf8.FullRune(b) { 605 r, l := utf8.DecodeRune(b) 606 runes = append(runes, r) 607 b = b[l:] 608 } 609 if len(b) > 0 { 610 fd.lastbits = make([]byte, len(b)) 611 copy(fd.lastbits, b) 612 } 613 // syscall.WriteConsole seems to fail, if given large buffer. 614 // So limit the buffer to 16000 characters. This number was 615 // discovered by experimenting with syscall.WriteConsole. 616 const maxWrite = 16000 617 for len(runes) > 0 { 618 m := len(runes) 619 if m > maxWrite { 620 m = maxWrite 621 } 622 chunk := runes[:m] 623 runes = runes[m:] 624 uint16s := utf16.Encode(chunk) 625 for len(uint16s) > 0 { 626 var written uint32 627 err := syscall.WriteConsole(fd.Sysfd, &uint16s[0], uint32(len(uint16s)), &written, nil) 628 if err != nil { 629 return 0, err 630 } 631 uint16s = uint16s[written:] 632 } 633 } 634 return n, nil 635 } 636 637 func (fd *FD) Pwrite(b []byte, off int64) (int, error) { 638 if err := fd.writeLock(); err != nil { 639 return 0, err 640 } 641 defer fd.writeUnlock() 642 643 fd.l.Lock() 644 defer fd.l.Unlock() 645 curoffset, e := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent) 646 if e != nil { 647 return 0, e 648 } 649 defer syscall.Seek(fd.Sysfd, curoffset, io.SeekStart) 650 o := syscall.Overlapped{ 651 OffsetHigh: uint32(off >> 32), 652 Offset: uint32(off), 653 } 654 var done uint32 655 e = syscall.WriteFile(fd.Sysfd, b, &done, &o) 656 if e != nil { 657 return 0, e 658 } 659 return int(done), nil 660 } 661 662 func (fd *FD) Writev(buf *[][]byte) (int64, error) { 663 if len(*buf) == 0 { 664 return 0, nil 665 } 666 if err := fd.writeLock(); err != nil { 667 return 0, err 668 } 669 defer fd.writeUnlock() 670 if race.Enabled { 671 race.ReleaseMerge(unsafe.Pointer(&ioSync)) 672 } 673 o := &fd.wop 674 o.InitBufs(buf) 675 n, err := wsrv.ExecIO(o, "WSASend", func(o *operation) error { 676 return syscall.WSASend(o.fd.Sysfd, &o.bufs[0], uint32(len(*buf)), &o.qty, 0, &o.o, nil) 677 }) 678 o.ClearBufs() 679 TestHookDidWritev(n) 680 consume(buf, int64(n)) 681 return int64(n), err 682 } 683 684 func (fd *FD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) { 685 if len(buf) == 0 { 686 return 0, nil 687 } 688 if err := fd.writeLock(); err != nil { 689 return 0, err 690 } 691 defer fd.writeUnlock() 692 o := &fd.wop 693 o.InitBuf(buf) 694 o.sa = sa 695 n, err := wsrv.ExecIO(o, "WSASendto", func(o *operation) error { 696 return syscall.WSASendto(o.fd.Sysfd, &o.buf, 1, &o.qty, 0, o.sa, &o.o, nil) 697 }) 698 return n, err 699 } 700 701 // Call ConnectEx. This doesn't need any locking, since it is only 702 // called when the descriptor is first created. This is here rather 703 // than in the net package so that it can use fd.wop. 704 func (fd *FD) ConnectEx(ra syscall.Sockaddr) error { 705 o := &fd.wop 706 o.sa = ra 707 _, err := wsrv.ExecIO(o, "ConnectEx", func(o *operation) error { 708 return ConnectExFunc(o.fd.Sysfd, o.sa, nil, 0, nil, &o.o) 709 }) 710 return err 711 } 712 713 func (fd *FD) acceptOne(s syscall.Handle, rawsa []syscall.RawSockaddrAny, o *operation) (string, error) { 714 // Submit accept request. 715 o.handle = s 716 o.rsan = int32(unsafe.Sizeof(rawsa[0])) 717 _, err := rsrv.ExecIO(o, "AcceptEx", func(o *operation) error { 718 return AcceptFunc(o.fd.Sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o) 719 }) 720 if err != nil { 721 CloseFunc(s) 722 return "acceptex", err 723 } 724 725 // Inherit properties of the listening socket. 726 err = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.Sysfd)), int32(unsafe.Sizeof(fd.Sysfd))) 727 if err != nil { 728 CloseFunc(s) 729 return "setsockopt", err 730 } 731 732 return "", nil 733 } 734 735 // Accept handles accepting a socket. The sysSocket parameter is used 736 // to allocate the net socket. 737 func (fd *FD) Accept(sysSocket func() (syscall.Handle, error)) (syscall.Handle, []syscall.RawSockaddrAny, uint32, string, error) { 738 if err := fd.readLock(); err != nil { 739 return syscall.InvalidHandle, nil, 0, "", err 740 } 741 defer fd.readUnlock() 742 743 o := &fd.rop 744 var rawsa [2]syscall.RawSockaddrAny 745 for { 746 s, err := sysSocket() 747 if err != nil { 748 return syscall.InvalidHandle, nil, 0, "", err 749 } 750 751 errcall, err := fd.acceptOne(s, rawsa[:], o) 752 if err == nil { 753 return s, rawsa[:], uint32(o.rsan), "", nil 754 } 755 756 // Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is 757 // returned here. These happen if connection reset is received 758 // before AcceptEx could complete. These errors relate to new 759 // connection, not to AcceptEx, so ignore broken connection and 760 // try AcceptEx again for more connections. 761 errno, ok := err.(syscall.Errno) 762 if !ok { 763 return syscall.InvalidHandle, nil, 0, errcall, err 764 } 765 switch errno { 766 case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET: 767 // ignore these and try again 768 default: 769 return syscall.InvalidHandle, nil, 0, errcall, err 770 } 771 } 772 } 773 774 func (fd *FD) Seek(offset int64, whence int) (int64, error) { 775 if err := fd.incref(); err != nil { 776 return 0, err 777 } 778 defer fd.decref() 779 780 fd.l.Lock() 781 defer fd.l.Unlock() 782 783 return syscall.Seek(fd.Sysfd, offset, whence) 784 } 785 786 // FindNextFile wraps syscall.FindNextFile. 787 func (fd *FD) FindNextFile(data *syscall.Win32finddata) error { 788 if err := fd.incref(); err != nil { 789 return err 790 } 791 defer fd.decref() 792 return syscall.FindNextFile(fd.Sysfd, data) 793 } 794 795 // Fchdir wraps syscall.Fchdir. 796 func (fd *FD) Fchdir() error { 797 if err := fd.incref(); err != nil { 798 return err 799 } 800 defer fd.decref() 801 return syscall.Fchdir(fd.Sysfd) 802 } 803 804 func (fd *FD) GetFileType() (uint32, error) { 805 if err := fd.incref(); err != nil { 806 return 0, err 807 } 808 defer fd.decref() 809 return syscall.GetFileType(fd.Sysfd) 810 } 811 812 func (fd *FD) GetFileInformationByHandle(data *syscall.ByHandleFileInformation) error { 813 if err := fd.incref(); err != nil { 814 return err 815 } 816 defer fd.decref() 817 return syscall.GetFileInformationByHandle(fd.Sysfd, data) 818 }