if (!fSuccess)
{
DWORD error = ::GetLastError();
- if (error == ERROR_PIPE_NOT_CONNECTED || error == ERROR_BROKEN_PIPE)
+ if (error == ERROR_PIPE_NOT_CONNECTED)
rgIpcPollHandles[index].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::HANGUP;
else
{
if (callback != nullptr)
- callback("Client connection error", error);
+ callback("Client connection error", -1);
rgIpcPollHandles[index].revents = (uint8_t)IpcStream::DiagnosticsIpc::PollEvents::ERR;
delete[] pHandles;
return -1;
if (!fSuccess)
{
- DWORD dwReadError = GetLastError();
- if (dwReadError == ERROR_IO_PENDING)
+ if (timeoutMs == InfiniteTimeout)
{
- // we are using Overlapped IO so
- // this is expected and not an error
- fSuccess = GetOverlappedResultEx(_hPipe,
- overlap,
- &nNumberOfBytesRead,
- timeoutMs,
- false) != 0;
- if (!fSuccess)
+ fSuccess = GetOverlappedResult(_hPipe,
+ overlap,
+ &nNumberOfBytesRead,
+ true) != 0;
+ }
+ else
+ {
+ DWORD dwError = GetLastError();
+ if (dwError == ERROR_IO_PENDING)
{
- DWORD dwOverlapError = GetLastError();
- switch (dwOverlapError)
+ DWORD dwWait = WaitForSingleObject(_oOverlap.hEvent, (DWORD)timeoutMs);
+ if (dwWait == WAIT_OBJECT_0)
+ {
+ // get the result
+ fSuccess = GetOverlappedResult(_hPipe,
+ overlap,
+ &nNumberOfBytesRead,
+ true) != 0;
+ }
+ else
{
- case ERROR_IO_INCOMPLETE:
- // should only happen if timeout is 0
- // this isn't technically an error, but the user requested a 0 timeout and the work hasn't been
- // completed yet, so we'll cancel.
- case WAIT_TIMEOUT:
- // We didn't complete the write in time... cancel the IO
- {
- fSuccess = CancelIoEx(_hPipe, overlap) != 0;
- if (!fSuccess)
- {
- DWORD dwCancelError = GetLastError();
- }
- else
- {
- fSuccess = GetOverlappedResult(_hPipe, overlap, &nNumberOfBytesRead, false) != 0;
- // failure either means we successfully cancelled the IO or something else went wrong.
- // not worth checking since we can't recover either way.
- }
- }
- break;
- case WAIT_IO_COMPLETION:
- // We aren't using IO Completion ports so we shouldn't see this...
- _ASSERTE(!"IO Completion error when not using IO Completion Ports");
- default:
- // unrecoverable errors
- _ASSERTE(!"IpcStream::Read - Unrecoverable error from GetOverlappedResult");
- break;
+ // cancel IO and ensure the cancel happened
+ if (CancelIo(_hPipe))
+ {
+ // check if the async write beat the cancellation
+ fSuccess = GetOverlappedResult(_hPipe, overlap, &nNumberOfBytesRead, true) != 0;
+ }
}
}
}
- else
- {
- // Other errors are unrecoverable and we should fall through to return failure
- _ASSERTE(!"IpcStream::Read - Unrecoverable error from ReadFile");
- }
+ // TODO: Add error handling.
}
nBytesRead = static_cast<uint32_t>(nNumberOfBytesRead);
if (!fSuccess)
{
- DWORD dwReadError = GetLastError();
- if (dwReadError == ERROR_IO_PENDING)
+ DWORD dwError = GetLastError();
+ if (dwError == ERROR_IO_PENDING)
{
- // we are using Overlapped IO so
- // this is expected and not an error
- fSuccess = GetOverlappedResultEx(_hPipe,
- overlap,
- &nNumberOfBytesWritten,
- timeoutMs,
- false) != 0;
- if (!fSuccess)
+ if (timeoutMs == InfiniteTimeout)
{
- DWORD dwOverlapError = GetLastError();
- switch (dwOverlapError)
+ // if we're waiting infinitely, don't bother with extra kernel call
+ fSuccess = GetOverlappedResult(_hPipe,
+ overlap,
+ &nNumberOfBytesWritten,
+ true) != 0;
+ }
+ else
+ {
+ DWORD dwWait = WaitForSingleObject(_oOverlap.hEvent, (DWORD)timeoutMs);
+ if (dwWait == WAIT_OBJECT_0)
+ {
+ // get the result
+ fSuccess = GetOverlappedResult(_hPipe,
+ overlap,
+ &nNumberOfBytesWritten,
+ true) != 0;
+ }
+ else
{
- case ERROR_IO_INCOMPLETE:
- // should only happen if timeout is 0
- // this isn't technically an error, but the user requested a 0 timeout and the work hasn't been
- // completed yet, so we'll cancel.
- case WAIT_TIMEOUT:
- // We didn't complete the write in time... cancel the IO
- {
- fSuccess = CancelIoEx(_hPipe, overlap) != 0;
- if (!fSuccess)
- {
- DWORD dwCancelError = GetLastError();
- }
- else
- {
- fSuccess = GetOverlappedResult(_hPipe, overlap, &nNumberOfBytesWritten, false) != 0;
- // failure either means we successfully cancelled the IO or something else went wrong.
- // not worth checking since we can't recover either way.
- }
- }
- break;
- case WAIT_IO_COMPLETION:
- // We aren't using IO Completion ports so we shouldn't see this...
- _ASSERTE(!"IO Completion error when not using IO Completion Ports");
- default:
- // unrecoverable errors
- _ASSERTE(!"IpcStream::Write - Unrecoverable error from GetOverlappedResult");
- break;
+ // cancel IO and ensure the cancel happened
+ if (CancelIo(_hPipe))
+ {
+ // check if the async write beat the cancellation
+ fSuccess = GetOverlappedResult(_hPipe, overlap, &nNumberOfBytesWritten, true) != 0;
+ }
}
}
}
- else
- {
- // Other errors are unrecoverable and we should fall through to return failure
- _ASSERTE(!"IpcStream::Write - Unrecoverable error from WriteFile");
- }
+ // TODO: Add error handling.
}
nBytesWritten = static_cast<uint32_t>(nNumberOfBytesWritten);
{
case IpcStream::DiagnosticsIpc::PollEvents::HANGUP:
((DiagnosticPort*)(rgIpcPollHandles[i].pUserData))->Reset(callback);
- STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - HUP :: Poll attempt: %d, connection %d hung up. Connect is reset.\n", nPollAttempts, i);
+ STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - HUP :: Poll attempt: %d, connection %d hung up.\n", nPollAttempts, i);
pollTimeoutMs = s_pollTimeoutMinMs;
break;
case IpcStream::DiagnosticsIpc::PollEvents::SIGNALED:
STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - SIG :: Poll attempt: %d, connection %d signalled.\n", nPollAttempts, i);
break;
case IpcStream::DiagnosticsIpc::PollEvents::ERR:
- ((DiagnosticPort*)(rgIpcPollHandles[i].pUserData))->Reset(callback);
- STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - ERR :: Poll attempt: %d, connection %d errored. Connection is reset.\n", nPollAttempts, i);
+ STRESS_LOG2(LF_DIAGNOSTICS_PORT, LL_INFO10, "IpcStreamFactory::GetNextAvailableStream - ERR :: Poll attempt: %d, connection %d errored.\n", nPollAttempts, i);
fSawError = true;
break;
case IpcStream::DiagnosticsIpc::PollEvents::NONE: