Menu

#15 Deadlock if backup fails due to not enough space for image

open
nobody
None
5
2012-06-04
2012-06-04
survivorx
No

The write threads exits with an error but the other compression thread still waits for the write thread to emty the queue. The main thread waits for all of those threads and thus deadlocks.

It can be fixed like this ("// <<" mark new lines):

void COdinManager::WaitToCompleteOperation(IWaitCallback* callback)
{
// wait until threads are completed without blocking the user interface
unsigned threadCount = GetThreadCount();
HANDLE* threadHandleArray = new HANDLE[threadCount];
bool ok = GetThreadHandles(threadHandleArray, threadCount);
if (!ok)
return;
ATLTRACE("WaitToCompleteOperation() entered.\n");

while (TRUE) {
DWORD result = MsgWaitForMultipleObjects(threadCount, threadHandleArray, FALSE, INFINITE, QS_ALLEVENTS);
if (this->WasError()) { // <<
ATLTRACE("Error while operation: %d\n", this->GetErrorMessage()); //<<
callback->OnAbort(); // << handle error in ui
Terminate(); // << free failed threads
break; // <<
} else // <<
if (result >= WAIT_OBJECT_0 && result < (DWORD)threadCount) {
ATLTRACE("event arrived: %d, thread id: %x\n", result, threadHandleArray[result]);
callback->OnThreadTerminated();
if (--threadCount == 0) {
ATLTRACE(" All worker threads are terminated now\n");
//ATLTRACE(" Total Bytes written: %lu\n", m_allThreads[1]->GetBytesWritten());
//ATLTRACE(" Total Bytes read: %lu\n", m_allThreads[0]->GetBytesRead());
if (NULL != fReadThread)
fVerifyCrc32 = fReadThread->GetCrc32();
callback->OnFinished();
Terminate(); // work is finished
break;
}
// setup new array with the remaining threads:
for (unsigned i=result; i<threadCount; i++)
threadHandleArray[i] = threadHandleArray[i+1];
}
else if (result == WAIT_OBJECT_0 + threadCount)
{
// ATLTRACE("windows msg arrived\n");
// process windows messages
MSG msg ;
while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
::DispatchMessage(&msg) ;
}
else if ( WAIT_FAILED) {
ATLTRACE("MsgWaitForMultipleObjects failed, last error is: %d\n", GetLastError());
callback->OnAbort();
break;
}
else
ATLTRACE("unusual return code from MsgWaitForMultipleObjects: %d\n", result);
}
delete [] threadHandleArray;
ATLTRACE("WaitToCompleteOperation() exited.\n");
}

Discussion


Log in to post a comment.