I have inherited some Windows TCP server code, only to find it does not work.
I call GetQueuedCompletionStatus()
and this generates the ERROR_CONNECTION_ABORTED
error.
Code that calls it:
unsigned int WinTCPServer::runWorker()
{
unsigned int returnValue = 0U;
bool bStayAlive = true;
while (bStayAlive)
{
// Wait for IOCP events.
DWORD bytesTransferred = 0U;
ULONG_PTR completionKey = 0U;
LPOVERLAPPED pOverlapped = NULL;
BOOL bResult = GetQueuedCompletionStatus(_hIOCP, &bytesTransferred, &completionKey, &pOverlapped, INFINITE);
if (FALSE == bResult)
{
// If pOverlapped == NULL then no packet was dequeued, the other parameters contain
// undefined values, and we can't tell which socket it was. If pOverlapped != NULL,
// the function has dequeued a failed completion packet.
if (pOverlapped == NULL)
{
std::string error = "GetQueuedCompletionStatus failed, unknown context, interface id: " + std::to_string(_interfaceID);
_consoleLog.AppError(__FILE__, __LINE__, error);
}
else
{
// If the completion key is zero, this was a shut-down post that failed
// (PostQueuedCompletionStatus with zero). This shouldn't happen! No real
// way of handling this gracefully.
if (0U == completionKey)
{
_consoleLog.PlatformError(__FILE__, __LINE__, "GetQueuedCompletionStatus failed", GetLastError());
std::string error = "TCP server shut down error, interface ID " + std::to_string(_interfaceID);
_consoleLog.AppError(__FILE__, __LINE__, error);
}
else
{
// Don't report client disconnections as errors.
DWORD lastError = GetLastError();
if ((ERROR_NETNAME_DELETED != lastError) && (ERROR_OPERATION_ABORTED != lastError))
{
_consoleLog.PlatformError(__FILE__, __LINE__, "GetQueuedCompletionStatus failed", lastError);
}
// Perform any outstanding actions on the overlapped operation.
WinTCPClientContext* pClientContext = reinterpret_cast<WinTCPClientContext*>(completionKey);
pClientContext->ProcessIncompleteOverlapped(pOverlapped);
// We don't want to use this client any more.
removeClient(*pClientContext);
}
}
}
else
{
// A null client context means the server is shutting down (i.e. has called
// PostQueuedCompletionStatus with a NULL value).
if (0U == completionKey)
{
bStayAlive = false;
}
else
{
// Convert the completion key into the client context.
WinTCPClientContext* pClientContext = reinterpret_cast<WinTCPClientContext*>(completionKey);
if (0U == bytesTransferred)
{
// This means a gracefull disconnection of the client.
// We should get this for every outstanding post (i.e.
// outstanding reads and writes).
pClientContext->ProcessIncompleteOverlapped(pOverlapped);
// We don't want to use this client any more.
removeClient(*pClientContext);
}
else
{
// Process the overlapped result
try
{
// Process the post.
pClientContext->ProcessOverlapped(pOverlapped, bytesTransferred);
}
catch (utility::CommsException& ex)
{
_consoleLog.PlatformError(ex.Filename(), ex.Line(), ex.Error(), ex.ErrorCode());
_consoleLog.StatusInfo(__FILE__, __LINE__, "client error, disconnecting");
// We don't want to use this client any more.
removeClient(*pClientContext);
}
catch (utility::Exception& ex)
{
_consoleLog.AppError(ex.Filename(), ex.Line(), ex.Error());
_consoleLog.StatusInfo(__FILE__, __LINE__, "client error, disconnecting");
// We don't want to use this client any more.
removeClient(*pClientContext);
}
}
}
}
}
return returnValue;
}
The server connects to a client and some message between the 2 are processed correctly. There are however, a couple of messages that cause this error and I have no idea why.
What are the causes of this error, and how can debug them?
This problem was actually nothing to do with the tcp comms. The application was throwing a deeply buried unhandled exception causing strange behavior.