Changeset 70481 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Jan 7, 2018 6:46:08 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/socket.cpp
r70401 r70481 165 165 /** Saved events which are only posted once. */ 166 166 uint32_t fEventsSaved; 167 /** Set if we're using the polling fallback. */ 168 bool fPollFallback; 169 /** Set if the fallback polling is active (event not set). */ 170 bool volatile fPollFallbackActive; 171 /** Set to shut down the fallback polling thread. */ 172 bool volatile fPollFallbackShutdown; 173 /** Socket use to wake up the select thread. */ 174 RTSOCKETNATIVE hPollFallbackNotifyW; 175 /** Socket the select thread always waits on. */ 176 RTSOCKETNATIVE hPollFallbackNotifyR; 177 /** The fallback polling thread. */ 178 RTTHREAD hPollFallbackThread; 167 179 #endif /* RT_OS_WINDOWS */ 168 180 } RTSOCKETINT; … … 189 201 static uint32_t volatile g_uWinSockInitedVersion = 0; 190 202 #endif 203 204 205 /********************************************************************************************************************************* 206 * Internal Functions * 207 *********************************************************************************************************************************/ 208 #ifdef RT_OS_WINDOWS 209 static void rtSocketPokePollFallbackThread(RTSOCKETINT *pThis); 210 #endif 211 191 212 192 213 … … 480 501 #endif 481 502 #ifdef RT_OS_WINDOWS 482 pThis->hEvent = WSA_INVALID_EVENT; 483 pThis->fPollEvts = 0; 484 pThis->fSubscribedEvts = 0; 485 pThis->fEventsSaved = 0; 503 pThis->hEvent = WSA_INVALID_EVENT; 504 pThis->fPollEvts = 0; 505 pThis->fSubscribedEvts = 0; 506 pThis->fEventsSaved = 0; 507 pThis->fPollFallback = g_uWinSockInitedVersion < MAKEWORD(2, 0) 508 || g_pfnWSACreateEvent == NULL 509 || g_pfnWSACloseEvent == NULL 510 || g_pfnWSAEventSelect == NULL 511 || g_pfnWSAEnumNetworkEvents == NULL; 512 pThis->fPollFallbackActive = false; 513 pThis->fPollFallbackShutdown = false; 514 pThis->hPollFallbackNotifyR = NIL_RTSOCKETNATIVE; 515 pThis->hPollFallbackNotifyW = NIL_RTSOCKETNATIVE; 516 pThis->hPollFallbackThread = NIL_RTTHREAD; 486 517 #endif 487 518 *ppSocket = pThis; … … 550 581 551 582 583 /** 584 * Wrapper around socketpair() for creating a local TCP connection. 585 * 586 * @returns IPRT status code. 587 * @param phServer Where to return the first native socket. 588 * @param phClient Where to return the second native socket. 589 */ 590 static int rtSocketCreateNativeTcpPair(RTSOCKETNATIVE *phServer, RTSOCKETNATIVE *phClient) 591 { 592 #ifdef RT_OS_WINDOWS 593 /* 594 * Initialize WinSock and make sure we got the necessary APIs. 595 */ 596 int rc = rtSocketInitWinsock(); 597 if (RT_FAILURE(rc)) 598 return rc; 599 AssertReturn(g_pfnsocket, VERR_NET_NOT_UNSUPPORTED); 600 AssertReturn(g_pfnclosesocket, VERR_NET_NOT_UNSUPPORTED); 601 AssertReturn(g_pfnsetsockopt, VERR_NET_NOT_UNSUPPORTED); 602 AssertReturn(g_pfnbind, VERR_NET_NOT_UNSUPPORTED); 603 AssertReturn(g_pfngetsockname, VERR_NET_NOT_UNSUPPORTED); 604 AssertReturn(g_pfnlisten, VERR_NET_NOT_UNSUPPORTED); 605 AssertReturn(g_pfnaccept, VERR_NET_NOT_UNSUPPORTED); 606 AssertReturn(g_pfnconnect, VERR_NET_NOT_UNSUPPORTED); 607 608 /* 609 * Create the "server" listen socket and the "client" socket. 610 */ 611 RTSOCKETNATIVE hListener = g_pfnsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 612 if (hListener == NIL_RTSOCKETNATIVE) 613 return rtSocketError(); 614 RTSOCKETNATIVE hClient = g_pfnsocket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 615 if (hClient != NIL_RTSOCKETNATIVE) 616 { 617 618 /* 619 * We let WinSock choose a port number when we bind. 620 */ 621 union 622 { 623 struct sockaddr_in Ip; 624 struct sockaddr Generic; 625 } uAddr; 626 RT_ZERO(uAddr); 627 uAddr.Ip.sin_family = AF_INET; 628 uAddr.Ip.sin_addr.s_addr = RT_H2N_U32_C(INADDR_LOOPBACK); 629 //uAddr.Ip.sin_port = 0; 630 int fReuse = 1; 631 rc = g_pfnsetsockopt(hListener, SOL_SOCKET, SO_REUSEADDR, (const char *)&fReuse, sizeof(fReuse)); 632 if (rc == 0) 633 { 634 rc = g_pfnbind(hListener, &uAddr.Generic, sizeof(uAddr.Ip)); 635 if (rc == 0) 636 { 637 /* 638 * Get the address the client should connect to. According to the docs, 639 * we cannot assume that getsockname sets the IP and family. 640 */ 641 RT_ZERO(uAddr); 642 int cbAddr = sizeof(uAddr.Ip); 643 rc = g_pfngetsockname(hListener, &uAddr.Generic, &cbAddr); 644 if (rc == 0) 645 { 646 uAddr.Ip.sin_family = AF_INET; 647 uAddr.Ip.sin_addr.s_addr = RT_H2N_U32_C(INADDR_LOOPBACK); 648 649 /* 650 * Listen, connect and accept. 651 */ 652 rc = g_pfnlisten(hListener, 1 /*cBacklog*/); 653 if (rc == 0) 654 { 655 rc = g_pfnconnect(hClient, &uAddr.Generic, sizeof(uAddr.Ip)); 656 if (rc == 0) 657 { 658 RTSOCKETNATIVE hServer = g_pfnaccept(hListener, NULL, NULL); 659 if (hServer != NIL_RTSOCKETNATIVE) 660 { 661 g_pfnclosesocket(hListener); 662 663 /* 664 * Done! 665 */ 666 *phServer = hServer; 667 *phClient = hClient; 668 return VINF_SUCCESS; 669 } 670 } 671 } 672 } 673 } 674 } 675 rc = rtSocketError(); 676 g_pfnclosesocket(hClient); 677 } 678 else 679 rc = rtSocketError(); 680 g_pfnclosesocket(hListener); 681 return rc; 682 683 #else 684 /* 685 * Got socket pair, so use it. 686 */ 687 int aSockets[2] = { -1, -1 }; 688 int (socketpair(AF_INET, SOCK_STREAM, IPPROTO_TCP, aSockets) == 0) 689 { 690 *phServer = aSockets[0]; 691 *phClient = aSockets[0]; 692 return VINF_SUCCESS; 693 } 694 return rtSocketError(); 695 #endif 696 } 697 698 699 /** 700 * Worker for RTTcpCreatePair. 701 * 702 * @returns IPRT status code. 703 * @param phServer Where to return the "server" side of the pair. 704 * @param phClient Where to return the "client" side of the pair. 705 * @note There is no server or client side, but we gotta call it something. 706 */ 707 DECLHIDDEN(int) rtSocketCreateTcpPair(RTSOCKET *phServer, RTSOCKET *phClient) 708 { 709 RTSOCKETNATIVE hServer = NIL_RTSOCKETNATIVE; 710 RTSOCKETNATIVE hClient = NIL_RTSOCKETNATIVE; 711 int rc = rtSocketCreateNativeTcpPair(&hServer, &hClient); 712 if (RT_SUCCESS(rc)) 713 { 714 rc = rtSocketCreateForNative(phServer, hServer); 715 if (RT_SUCCESS(rc)) 716 { 717 rc = rtSocketCreateForNative(phClient, hClient); 718 if (RT_SUCCESS(rc)) 719 return VINF_SUCCESS; 720 RTSocketRelease(*phServer); 721 } 722 else 723 { 724 #ifdef RT_OS_WINDOWS 725 g_pfnclosesocket(hServer); 726 #else 727 close(hServer); 728 #endif 729 } 730 #ifdef RT_OS_WINDOWS 731 g_pfnclosesocket(hClient); 732 #else 733 close(hClient); 734 #endif 735 } 736 737 *phServer = NIL_RTSOCKET; 738 *phClient = NIL_RTSOCKET; 739 return rc; 740 } 741 742 552 743 RTDECL(uint32_t) RTSocketRetain(RTSOCKET hSocket) 553 744 { … … 580 771 if (ASMAtomicCmpXchgBool(&pThis->fClosed, true, false)) 581 772 { 773 #ifdef RT_OS_WINDOWS 774 /* 775 * Poke the polling thread if active and give it a small chance to stop. 776 */ 777 if ( pThis->fPollFallback 778 && pThis->hPollFallbackThread != NIL_RTTHREAD) 779 { 780 ASMAtomicWriteBool(&pThis->fPollFallbackShutdown, true); 781 rtSocketPokePollFallbackThread(pThis); 782 int rc2 = RTThreadWait(pThis->hPollFallbackThread, RT_MS_1SEC, NULL); 783 if (RT_SUCCESS(rc2)) 784 pThis->hPollFallbackThread = NIL_RTTHREAD; 785 } 786 #endif 787 582 788 /* 583 789 * Close the native handle. … … 606 812 #ifdef RT_OS_WINDOWS 607 813 /* 608 * Close the event.814 * Windows specific polling cleanup. 609 815 */ 610 816 WSAEVENT hEvent = pThis->hEvent; … … 612 818 { 613 819 pThis->hEvent = WSA_INVALID_EVENT; 614 Assert(g_pfnWSACloseEvent); 615 if (g_pfnWSACloseEvent) 616 g_pfnWSACloseEvent(hEvent); 820 if (!pThis->fPollFallback) 821 { 822 Assert(g_pfnWSACloseEvent); 823 if (g_pfnWSACloseEvent) 824 g_pfnWSACloseEvent(hEvent); 825 } 826 else 827 CloseHandle(hEvent); 828 } 829 830 if (pThis->fPollFallback) 831 { 832 if (pThis->hPollFallbackNotifyW != NIL_RTSOCKETNATIVE) 833 { 834 g_pfnclosesocket(pThis->hPollFallbackNotifyW); 835 pThis->hPollFallbackNotifyW = NIL_RTSOCKETNATIVE; 836 } 837 838 if (pThis->hPollFallbackThread != NIL_RTTHREAD) 839 { 840 int rc2 = RTThreadWait(pThis->hPollFallbackThread, RT_MS_1MIN / 2, NULL); 841 AssertRC(rc2); 842 pThis->hPollFallbackThread = NIL_RTTHREAD; 843 } 844 845 if (pThis->hPollFallbackNotifyR != NIL_RTSOCKETNATIVE) 846 { 847 g_pfnclosesocket(pThis->hPollFallbackNotifyR); 848 pThis->hPollFallbackNotifyR = NIL_RTSOCKETNATIVE; 849 } 617 850 } 618 851 #endif … … 1699 1932 1700 1933 1701 RTDECL(int) RTSocketSelectOneEx(RTSOCKET hSocket, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies) 1702 { 1703 /* 1704 * Validate input. 1705 */ 1706 RTSOCKETINT *pThis = hSocket; 1707 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 1708 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE); 1709 AssertPtrReturn(pfEvents, VERR_INVALID_PARAMETER); 1710 AssertReturn(!(fEvents & ~RTSOCKET_EVT_VALID_MASK), VERR_INVALID_PARAMETER); 1711 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE); 1712 1934 /** 1935 * Internal worker for RTSocketSelectOneEx and rtSocketPollCheck (fallback) 1936 * 1937 * @returns IPRT status code 1938 * @param pThis The socket (valid). 1939 * @param fEvents The events to select for. 1940 * @param pfEvents Where to return the events. 1941 * @param cMillies How long to select for, in milliseconds. 1942 */ 1943 static int rtSocketSelectOneEx(RTSOCKET pThis, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies) 1944 { 1713 1945 RTSOCKETNATIVE hNative = pThis->hNative; 1714 1946 if (hNative == NIL_RTSOCKETNATIVE) … … 1787 2019 #endif 1788 2020 return rc; 2021 } 2022 2023 2024 RTDECL(int) RTSocketSelectOneEx(RTSOCKET hSocket, uint32_t fEvents, uint32_t *pfEvents, RTMSINTERVAL cMillies) 2025 { 2026 /* 2027 * Validate input. 2028 */ 2029 RTSOCKETINT *pThis = hSocket; 2030 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 2031 AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE); 2032 AssertPtrReturn(pfEvents, VERR_INVALID_PARAMETER); 2033 AssertReturn(!(fEvents & ~RTSOCKET_EVT_VALID_MASK), VERR_INVALID_PARAMETER); 2034 AssertReturn(RTMemPoolRefCount(pThis) >= (pThis->cUsers ? 2U : 1U), VERR_CALLER_NO_REFERENCE); 2035 2036 return rtSocketSelectOneEx(pThis, fEvents, pfEvents, cMillies); 1789 2037 } 1790 2038 … … 2274 2522 } 2275 2523 else 2276 rc = VERR_NET_NOT_UNSUPPORTED; 2524 { 2525 AssertCompile(WSA_INVALID_EVENT == (WSAEVENT)NULL); 2526 pThis->hEvent = CreateEventW(NULL, TRUE /*fManualReset*/, FALSE /*fInitialState*/, NULL /*pwszName*/); 2527 *phNative = (RTHCINTPTR)pThis->hEvent; 2528 if (pThis->hEvent == WSA_INVALID_EVENT) 2529 rc = RTErrConvertFromWin32(GetLastError()); 2530 } 2277 2531 2278 2532 rtSocketUnlock(pThis); … … 2288 2542 2289 2543 /** 2544 * Fallback poller thread. 2545 * 2546 * @returns VINF_SUCCESS. 2547 * @param hSelf The thread handle. 2548 * @param pvUser Socket instance data. 2549 */ 2550 static DECLCALLBACK(int) rtSocketPollFallbackThreadProc(RTTHREAD hSelf, void *pvUser) 2551 { 2552 RTSOCKETINT *pThis = (RTSOCKETINT *)pvUser; 2553 RT_NOREF(hSelf); 2554 # define __WSAFDIsSet g_pfn__WSAFDIsSet 2555 2556 /* 2557 * The execution loop. 2558 */ 2559 while (!ASMAtomicReadBool(&pThis->fPollFallbackShutdown)) 2560 { 2561 /* 2562 * Do the selecting (with a 15 second timeout because that seems like a good idea). 2563 */ 2564 struct fd_set SetRead; 2565 struct fd_set SetWrite; 2566 struct fd_set SetXcpt; 2567 2568 FD_ZERO(&SetRead); 2569 FD_ZERO(&SetWrite); 2570 FD_ZERO(&SetXcpt); 2571 2572 FD_SET(pThis->hPollFallbackNotifyR, &SetRead); 2573 FD_SET(pThis->hPollFallbackNotifyR, &SetXcpt); 2574 2575 bool fActive = ASMAtomicReadBool(&pThis->fPollFallbackActive); 2576 uint32_t fEvents; 2577 if (!fActive) 2578 fEvents = 0; 2579 else 2580 { 2581 fEvents = ASMAtomicReadU32(&pThis->fSubscribedEvts); 2582 if (fEvents & RTPOLL_EVT_READ) 2583 FD_SET(pThis->hNative, &SetRead); 2584 if (fEvents & RTPOLL_EVT_WRITE) 2585 FD_SET(pThis->hNative, &SetWrite); 2586 if (fEvents & RTPOLL_EVT_ERROR) 2587 FD_SET(pThis->hNative, &SetXcpt); 2588 } 2589 2590 struct timeval Timeout; 2591 Timeout.tv_sec = 15; 2592 Timeout.tv_usec = 0; 2593 int rc = g_pfnselect(INT_MAX /*ignored*/, &SetRead, &SetWrite, &SetXcpt, &Timeout); 2594 2595 /* Stop immediately if told to shut down. */ 2596 if (ASMAtomicReadBool(&pThis->fPollFallbackShutdown)) 2597 break; 2598 2599 /* 2600 * Process the result. 2601 */ 2602 if (rc > 0) 2603 { 2604 /* First the socket we're listening on. */ 2605 if ( fEvents 2606 && ( FD_ISSET(pThis->hNative, &SetRead) 2607 || FD_ISSET(pThis->hNative, &SetWrite) 2608 || FD_ISSET(pThis->hNative, &SetXcpt)) ) 2609 { 2610 ASMAtomicWriteBool(&pThis->fPollFallbackActive, false); 2611 SetEvent(pThis->hEvent); 2612 } 2613 2614 /* Then maintain the notification pipe. (We only read one byte here 2615 because we're overly paranoid wrt socket switching to blocking mode.) */ 2616 if (FD_ISSET(pThis->hPollFallbackNotifyR, &SetRead)) 2617 { 2618 char chIgnored; 2619 g_pfnrecv(pThis->hPollFallbackNotifyR, &chIgnored, sizeof(chIgnored), MSG_NOSIGNAL); 2620 } 2621 } 2622 else 2623 AssertMsg(rc == 0, ("%Rrc\n", rtSocketError())); 2624 } 2625 2626 # undef __WSAFDIsSet 2627 return VINF_SUCCESS; 2628 } 2629 2630 2631 /** 2632 * Pokes the fallback thread, making sure it gets out of whatever it's stuck in. 2633 * 2634 * @param pThis The socket handle. 2635 */ 2636 static void rtSocketPokePollFallbackThread(RTSOCKETINT *pThis) 2637 { 2638 Assert(pThis->fPollFallback); 2639 if (pThis->hPollFallbackThread != NIL_RTTHREAD) 2640 { 2641 int cbWritten = g_pfnsend(pThis->hPollFallbackNotifyW, "!", 1, MSG_NOSIGNAL); 2642 AssertMsg(cbWritten == 1, ("cbWritten=%d err=%Rrc\n", rtSocketError())); 2643 RT_NOREF_PV(cbWritten); 2644 } 2645 } 2646 2647 2648 /** 2649 * Called by rtSocketPollStart to make the thread start selecting on the socket. 2650 * 2651 * @returns 0 on success, RTPOLL_EVT_ERROR on failure. 2652 * @param pThis The socket handle. 2653 */ 2654 static uint32_t rtSocketPollFallbackStart(RTSOCKETINT *pThis) 2655 { 2656 /* 2657 * Reset the event and tell the thread to start selecting on the socket. 2658 */ 2659 ResetEvent(pThis->hEvent); 2660 ASMAtomicWriteBool(&pThis->fPollFallbackActive, true); 2661 2662 /* 2663 * Wake up the thread the thread. 2664 */ 2665 if (pThis->hPollFallbackThread != NIL_RTTHREAD) 2666 rtSocketPokePollFallbackThread(pThis); 2667 else 2668 { 2669 /* 2670 * Not running, need to set it up and start it. 2671 */ 2672 AssertLogRelReturn(pThis->hEvent != NULL && pThis->hEvent != INVALID_HANDLE_VALUE, RTPOLL_EVT_ERROR); 2673 2674 /* Create the notification socket pair. */ 2675 int rc; 2676 if (pThis->hPollFallbackNotifyR == NIL_RTSOCKETNATIVE) 2677 { 2678 rc = rtSocketCreateNativeTcpPair(&pThis->hPollFallbackNotifyW, &pThis->hPollFallbackNotifyR); 2679 AssertLogRelRCReturn(rc, RTPOLL_EVT_ERROR); 2680 2681 /* Make the read end non-blocking (not fatal). */ 2682 u_long fNonBlocking = 1; 2683 rc = g_pfnioctlsocket(pThis->hPollFallbackNotifyR, FIONBIO, &fNonBlocking); 2684 AssertLogRelMsg(rc == 0, ("rc=%#x %Rrc\n", rc, rtSocketError())); 2685 } 2686 2687 /* Finally, start the thread. ASSUME we don't need too much stack. */ 2688 rc = RTThreadCreate(&pThis->hPollFallbackThread, rtSocketPollFallbackThreadProc, pThis, 2689 _128K, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "sockpoll"); 2690 AssertLogRelRCReturn(rc, RTPOLL_EVT_ERROR); 2691 } 2692 return 0; 2693 } 2694 2695 2696 /** 2290 2697 * Undos the harm done by WSAEventSelect. 2291 2698 * … … 2298 2705 if (pThis->fSubscribedEvts) 2299 2706 { 2300 if (g_pfnWSAEventSelect && g_pfnioctlsocket) 2301 { 2302 if (g_pfnWSAEventSelect(pThis->hNative, WSA_INVALID_EVENT, 0) == 0) 2707 if (!pThis->fPollFallback) 2708 { 2709 Assert(g_pfnWSAEventSelect && g_pfnioctlsocket); 2710 if (g_pfnWSAEventSelect && g_pfnioctlsocket) 2303 2711 { 2304 pThis->fSubscribedEvts = 0; 2305 2306 /* 2307 * Switch back to blocking mode if that was the state before the 2308 * operation. 2309 */ 2310 if (pThis->fBlocking) 2712 if (g_pfnWSAEventSelect(pThis->hNative, WSA_INVALID_EVENT, 0) == 0) 2311 2713 { 2312 u_long fNonBlocking = 0; 2313 int rc2 = g_pfnioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking); 2314 if (rc2 != 0) 2714 pThis->fSubscribedEvts = 0; 2715 2716 /* 2717 * Switch back to blocking mode if that was the state before the 2718 * operation. 2719 */ 2720 if (pThis->fBlocking) 2315 2721 { 2316 rc = rtSocketError(); 2317 AssertMsgFailed(("%Rrc; rc2=%d\n", rc, rc2)); 2722 u_long fNonBlocking = 0; 2723 int rc2 = g_pfnioctlsocket(pThis->hNative, FIONBIO, &fNonBlocking); 2724 if (rc2 != 0) 2725 { 2726 rc = rtSocketError(); 2727 AssertMsgFailed(("%Rrc; rc2=%d\n", rc, rc2)); 2728 } 2318 2729 } 2730 } 2731 else 2732 { 2733 rc = rtSocketError(); 2734 AssertMsgFailed(("%Rrc\n", rc)); 2319 2735 } 2320 2736 } 2321 2737 else 2322 2738 { 2323 rc = rtSocketError();2324 AssertMsgFailed(("%Rrc\n", rc));2739 Assert(pThis->fPollFallback); 2740 rc = VINF_SUCCESS; 2325 2741 } 2326 2742 } 2743 /* 2744 * Just clear the event mask as we never started waiting if we get here. 2745 */ 2327 2746 else 2328 rc = VERR_NET_NOT_UNSUPPORTED;2747 ASMAtomicWriteU32(&pThis->fSubscribedEvts, 0); 2329 2748 } 2330 2749 return rc; … … 2341 2760 static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents) 2342 2761 { 2343 LONG fNetworkEvents = 0;2344 if (fEvents & RTPOLL_EVT_READ)2345 fNetworkEvents |= FD_READ;2346 if (fEvents & RTPOLL_EVT_WRITE)2347 fNetworkEvents |= FD_WRITE;2348 if (fEvents & RTPOLL_EVT_ERROR)2349 fNetworkEvents |= FD_CLOSE;2350 LogFlowFunc(("fNetworkEvents=%#x\n", fNetworkEvents));2351 int rc;2352 if (g_pfnWSAEventSelect)2353 { 2762 if (!pThis->fPollFallback) 2763 { 2764 LONG fNetworkEvents = 0; 2765 if (fEvents & RTPOLL_EVT_READ) 2766 fNetworkEvents |= FD_READ; 2767 if (fEvents & RTPOLL_EVT_WRITE) 2768 fNetworkEvents |= FD_WRITE; 2769 if (fEvents & RTPOLL_EVT_ERROR) 2770 fNetworkEvents |= FD_CLOSE; 2771 LogFlowFunc(("fNetworkEvents=%#x\n", fNetworkEvents)); 2772 2354 2773 if (g_pfnWSAEventSelect(pThis->hNative, pThis->hEvent, fNetworkEvents) == 0) 2355 2774 { … … 2357 2776 return VINF_SUCCESS; 2358 2777 } 2359 rc = rtSocketError(); 2778 2779 int rc = rtSocketError(); 2360 2780 AssertMsgFailed(("fNetworkEvents=%#x rc=%Rrc\n", fNetworkEvents, rtSocketError())); 2361 } 2362 else 2363 rc = VERR_NET_NOT_UNSUPPORTED; 2364 return rc; 2781 return rc; 2782 } 2783 2784 /* 2785 * Update the events we're waiting for. Caller will poke/start the thread. later 2786 */ 2787 ASMAtomicWriteU32(&pThis->fSubscribedEvts, fEvents); 2788 return VINF_SUCCESS; 2365 2789 } 2366 2790 … … 2389 2813 rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents); 2390 2814 2391 /* Get the event mask, ASSUMES that WSAEnumNetworkEvents doesn't clear stuff. */ 2392 if (g_pfnWSAEnumNetworkEvents) 2393 { 2815 if (!pThis->fPollFallback) 2816 { 2817 /* Atomically get pending events and reset the event semaphore. */ 2818 Assert(g_pfnWSAEnumNetworkEvents); 2394 2819 WSANETWORKEVENTS NetEvts; 2395 2820 RT_ZERO(NetEvts); … … 2420 2845 rc = rtSocketError(); 2421 2846 } 2422 else if (RT_SUCCESS(rc)) 2423 rc = VERR_NET_NOT_UNSUPPORTED; 2424 2425 /* Fall back on select if we hit an error above. */ 2426 if (RT_FAILURE(rc)) 2427 { 2428 rc = RTSocketSelectOneEx(pThis, fEvents, &fRetEvents, 0); 2429 if (RT_FAILURE(rc)) 2847 2848 /* Fall back on select if we hit an error above or is using fallback polling. */ 2849 if (pThis->fPollFallback || RT_FAILURE(rc)) 2850 { 2851 rc = rtSocketSelectOneEx(pThis, fEvents & RTPOLL_EVT_ERROR ? fEvents | RTPOLL_EVT_READ : fEvents, &fRetEvents, 0); 2852 if (RT_SUCCESS(rc)) 2853 { 2854 /* rtSocketSelectOneEx may return RTPOLL_EVT_READ on disconnect. Use 2855 getpeername to fix this. */ 2856 if ((fRetEvents & (RTPOLL_EVT_READ | RTPOLL_EVT_ERROR)) == RTPOLL_EVT_READ) 2857 { 2858 # if 0 /* doens't work */ 2859 rtSocketErrorReset(); 2860 char chIgn; 2861 rc = g_pfnrecv(pThis->hNative, &chIgn, 0, MSG_NOSIGNAL); 2862 rc = rtSocketError(); 2863 if (RT_FAILURE(rc)) 2864 fRetEvents |= RTPOLL_EVT_ERROR; 2865 2866 rc = g_pfnsend(pThis->hNative, &chIgn, 0, MSG_NOSIGNAL); 2867 rc = rtSocketError(); 2868 if (RT_FAILURE(rc)) 2869 fRetEvents |= RTPOLL_EVT_ERROR; 2870 2871 RTSOCKADDRUNION u; 2872 int cbAddr = sizeof(u); 2873 if (g_pfngetpeername(pThis->hNative, &u.Addr, &cbAddr) == SOCKET_ERROR) 2874 fRetEvents |= RTPOLL_EVT_ERROR; 2875 # endif 2876 /* If no bytes are available, assume error condition. */ 2877 u_long cbAvail = 0; 2878 rc = ioctlsocket(pThis->hNative, FIONREAD, &cbAvail); 2879 if (rc == 0 && cbAvail == 0) 2880 fRetEvents |= RTPOLL_EVT_ERROR; 2881 } 2882 fRetEvents &= fEvents | RTPOLL_EVT_ERROR; 2883 } 2884 else if (rc == VERR_TIMEOUT) 2430 2885 fRetEvents = 0; 2431 } 2432 2433 #else /* RT_OS_OS2 */ 2886 else 2887 fRetEvents |= RTPOLL_EVT_ERROR; 2888 } 2889 2890 # else /* RT_OS_OS2 */ 2434 2891 int aFds[4] = { pThis->hNative, pThis->hNative, pThis->hNative, -1 }; 2435 2892 int rc = os2_select(aFds, 1, 1, 1, 0); … … 2444 2901 fRetEvents &= fEvents; 2445 2902 } 2446 # endif /* RT_OS_OS2 */2903 # endif /* RT_OS_OS2 */ 2447 2904 2448 2905 LogFlowFunc(("fRetEvents=%#x\n", fRetEvents)); … … 2524 2981 ASMAtomicDecU32(&pThis->cUsers); 2525 2982 } 2983 # ifdef RT_OS_WINDOWS 2984 /* 2985 * Kick the poller thread on if this is the final entry and we're in 2986 * winsock 1.x fallback mode. 2987 */ 2988 else if (pThis->fPollFallback && fFinalEntry) 2989 fRetEvents = rtSocketPollFallbackStart(pThis); 2990 # endif 2526 2991 2527 2992 return fRetEvents; … … 2554 3019 RT_NOREF_PV(fFinalEntry); 2555 3020 2556 /* Harvest events and clear the event mask for the next round of polling. */ 3021 # ifdef RT_OS_WINDOWS 3022 /* 3023 * Deactivate the poll thread if we're in winsock 1.x fallback poll mode. 3024 */ 3025 if ( pThis->fPollFallback 3026 && pThis->hPollFallbackThread != NIL_RTTHREAD) 3027 { 3028 ASMAtomicWriteU32(&pThis->fSubscribedEvts, 0); 3029 if (ASMAtomicXchgBool(&pThis->fPollFallbackActive, false)) 3030 rtSocketPokePollFallbackThread(pThis); 3031 } 3032 # endif 3033 3034 /* 3035 * Harvest events and clear the event mask for the next round of polling. 3036 */ 2557 3037 uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents); 2558 3038 # ifdef RT_OS_WINDOWS
Note:
See TracChangeset
for help on using the changeset viewer.