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