Win wsa select event (#342)
* Fix #323: Missing SelectInterrupt implementation for Windows Using WSAEventSelect, WSAWaitForMultipleEvents and WSAEnumNetworkEvents to emulate poll() with an interrupt-event. * Cleanup * Fixed incomplete comment. * Switched ifdefs to support other Unixes with pipe file descriptors * Fixed: SelectInterrupt fallback code for getFd()==-1 && getEvent()==nullptr converted a PollResultType::Timeout into a ReadyForRead causing the HttpClient to fail because it uses a hard-coded "SelectInterrupt" instance that doesn't implement getFd() and getEvent(). * Fixed gcc compile errors * - HttpClient now uses the SelectInterruptFactory - Fixed wrong ix::poll result when using Windows WSA functions * We must deselect the networkevents from the socket event. Otherwise the socket will report states that aren't there.
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							9f00428d57
						
					
				
				
					commit
					1f2895a469
				
			@@ -47,6 +47,8 @@ namespace ix
 | 
			
		||||
                                int sockfd,
 | 
			
		||||
                                const SelectInterruptPtr& selectInterrupt)
 | 
			
		||||
    {
 | 
			
		||||
        PollResultType pollResult = PollResultType::ReadyForRead;
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // We used to use ::select to poll but on Android 9 we get large fds out of
 | 
			
		||||
        // ::connect which crash in FD_SET as they are larger than FD_SETSIZE. Switching
 | 
			
		||||
@@ -68,9 +70,11 @@ namespace ix
 | 
			
		||||
 | 
			
		||||
        // File descriptor used to interrupt select when needed
 | 
			
		||||
        int interruptFd = -1;
 | 
			
		||||
        void* interruptEvent = nullptr;
 | 
			
		||||
        if (selectInterrupt)
 | 
			
		||||
        {
 | 
			
		||||
            interruptFd = selectInterrupt->getFd();
 | 
			
		||||
            interruptEvent = selectInterrupt->getEvent();
 | 
			
		||||
 | 
			
		||||
            if (interruptFd != -1)
 | 
			
		||||
            {
 | 
			
		||||
@@ -78,11 +82,21 @@ namespace ix
 | 
			
		||||
                fds[1].fd = interruptFd;
 | 
			
		||||
                fds[1].events = POLLIN;
 | 
			
		||||
            }
 | 
			
		||||
            else if (interruptEvent == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                // Emulation mode: SelectInterrupt neither supports file descriptors nor events
 | 
			
		||||
 | 
			
		||||
                // Check the selectInterrupt for requests before doing the poll().
 | 
			
		||||
                if (readSelectInterruptRequest(selectInterrupt, &pollResult))
 | 
			
		||||
                {
 | 
			
		||||
                    return pollResult;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        int ret = ix::poll(fds, nfds, timeoutMs);
 | 
			
		||||
        void* event = interruptEvent; // ix::poll will set event to nullptr if it wasn't signaled
 | 
			
		||||
        int ret = ix::poll(fds, nfds, timeoutMs, &event);
 | 
			
		||||
 | 
			
		||||
        PollResultType pollResult = PollResultType::ReadyForRead;
 | 
			
		||||
        if (ret < 0)
 | 
			
		||||
        {
 | 
			
		||||
            pollResult = PollResultType::Error;
 | 
			
		||||
@@ -90,20 +104,19 @@ namespace ix
 | 
			
		||||
        else if (ret == 0)
 | 
			
		||||
        {
 | 
			
		||||
            pollResult = PollResultType::Timeout;
 | 
			
		||||
        }
 | 
			
		||||
        else if (interruptFd != -1 && fds[1].revents & POLLIN)
 | 
			
		||||
        {
 | 
			
		||||
            uint64_t value = selectInterrupt->read();
 | 
			
		||||
            if (selectInterrupt && interruptFd == -1 && interruptEvent == nullptr)
 | 
			
		||||
            {
 | 
			
		||||
                // Emulation mode: SelectInterrupt neither supports fd nor events
 | 
			
		||||
 | 
			
		||||
            if (value == SelectInterrupt::kSendRequest)
 | 
			
		||||
            {
 | 
			
		||||
                pollResult = PollResultType::SendRequest;
 | 
			
		||||
            }
 | 
			
		||||
            else if (value == SelectInterrupt::kCloseRequest)
 | 
			
		||||
            {
 | 
			
		||||
                pollResult = PollResultType::CloseRequest;
 | 
			
		||||
                // Check the selectInterrupt for requests
 | 
			
		||||
                readSelectInterruptRequest(selectInterrupt, &pollResult);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if ((interruptFd != -1 && fds[1].revents & POLLIN) || (interruptEvent != nullptr && event != nullptr))
 | 
			
		||||
        {
 | 
			
		||||
            // The InterruptEvent was signaled
 | 
			
		||||
            readSelectInterruptRequest(selectInterrupt, &pollResult);
 | 
			
		||||
        }
 | 
			
		||||
        else if (sockfd != -1 && readyToRead && fds[0].revents & POLLIN)
 | 
			
		||||
        {
 | 
			
		||||
            pollResult = PollResultType::ReadyForRead;
 | 
			
		||||
@@ -143,6 +156,25 @@ namespace ix
 | 
			
		||||
        return pollResult;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Socket::readSelectInterruptRequest(const SelectInterruptPtr& selectInterrupt,
 | 
			
		||||
                                            PollResultType* pollResult)
 | 
			
		||||
    {
 | 
			
		||||
        uint64_t value = selectInterrupt->read();
 | 
			
		||||
 | 
			
		||||
        if (value == SelectInterrupt::kSendRequest)
 | 
			
		||||
        {
 | 
			
		||||
            *pollResult = PollResultType::SendRequest;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        else if (value == SelectInterrupt::kCloseRequest)
 | 
			
		||||
        {
 | 
			
		||||
            *pollResult = PollResultType::CloseRequest;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    PollResultType Socket::isReadyToRead(int timeoutMs)
 | 
			
		||||
    {
 | 
			
		||||
        if (_sockfd == -1)
 | 
			
		||||
@@ -171,6 +203,11 @@ namespace ix
 | 
			
		||||
        return _selectInterrupt->notify(wakeUpCode);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Socket::isWakeUpFromPollSupported()
 | 
			
		||||
    {
 | 
			
		||||
        return _selectInterrupt->getFd() != -1 || _selectInterrupt->getEvent() != nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool Socket::accept(std::string& errMsg)
 | 
			
		||||
    {
 | 
			
		||||
        if (_sockfd == -1)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user