Crash with overlapped RS232 communication
I have a quite misterous problem. I am developing a windows application which is using the serial port for data transfere. I have developed a serial class based on the MSDN article Serial Communications in Win32. My application uses asnychron communication with overlapped structure.
The communication at the first sight is OK. But if there are more copies of my applications running on the same PC using DIFFERNET serial ports, after few day of running and receiving datas suddenly appears the following messagebox by each one of the application at the same time:
Runtime Error! Program: myapp.exe This application has requested the Runtime to terminate it in an unusual way.
Each one of the applications stops receiving datas through the serial port, but their GUI is still active. As soon as I press the OK button on the dialog, each application closes.
I have succeed to figure out, that there is some kind of memory leak. The memory grows slowly and when it comes to certain point the Runtime error messagebox appears. While the messagebox is on the command returns with error and the overlapped event is not created!
OVERLAPPED osReader = {0};
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
I guess I have to have some problem in the receiving routine. I went through my code several times but I couldn't find the error. There are 3 threads running 1 for the GUI, 1 for the serial data receiving and 1 for the serial data processing. The data are transfered between threads with deques.
What is very strange this error only happens if more than 1 of my applications are running. By 1 application everything is OK and the memory also stays at the same level.
Here is the receiving routine:
int UModulSerial::ReceiveVoid(LPVOID Buffer, int &NumberOfBytesToRead)
{
//overlapped read, it's possible, that we have to wait with waitforsingle object till the read operation finishes
if (m_bOverlapped)
{
CMutex mutRead;
CSingleLock lock(&mutRead,TRUE); //this will block other processes to read from the com port till our operation finishes
m_sError = "";
m_iErrNumber = 0;
DWORD NumberOfBytesReceived=0;
OVERLAPPED osReader = {0};
osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (osReader.hEvent == NULL)
{
SetErrorMessage(ERROR_CREATING_EVENT);
return -1;
}
int Read_Error = ReadFile
(
m_hSerPort, // handle of file to read
Buffer, // pointer to buffer that receives data
NumberOfBytesToRead, // number of bytes to read
&NumberOfBytesReceived, // pointer to number of bytes read
&osReader // pointer to OVERLAPPED structure for data
);
if (!Read_Error)
{
DWORD LastErrorCode = GetLastError();
if (LastErrorCode == ERROR_IO_PENDING) //if the read is not yet finished, wait till it finishes, or timeouts
{
DWORD dwRes = WaitForSingleObject(osReader.hEvent, m_Comtimeout.ReadTotalTimeoutConstant);
switch(dwRes)
{
case WAIT_OBJECT_0: // Read completed, transfer the overlapped result to our buffer.
if (!GetOverlappedResult(m_hSerPort, &osReader, &NumberOfBytesReceived, FALSE))
{
//if there was an error during transfering the overlapped structure to our buffer
SetErrorMessage(GetLastError());
CloseHandle(osReader.hEvent);
return -1;
}
else
{
//when the transfer was succesful, but the number of read bytes are not equal to requested than error
if(NumberOfBytesToRead != NumberOfBytesReceived)
{
NumberOfBytesToRead = NumberOfBytesReceived;
SetErrorMessage(ERROR_TIMEOUT);
CloseHandle(osReader.hEvent);
return -1;
}
}
break;
case WAIT_TIMEOUT:
//if there was a timeout during the read operation, than cancel the reading and return with error
SetErrorMessage(ERROR_TIMEOUT);
CancelIo(m_hSerPort);
//we call this to get how many bytes were read till the timeout
GetOverlappedResult(m_hSerPort, &osReader, &NumberOfBytesReceived, FALSE);
//maybe it was timeout but we received all the bytes we requested, in such case everything is ok
if (NumberOfBytesToRead != NumberOfBytesReceived)
{
CloseHandle(osReader.hEvent);
NumberOfBytesToRead = NumberOfBytesReceived;
return -1;
}
else
break;
break;
default:
//this indicates, that there is a problem with the overlapped eventhandler
SetErrorMessage(-1);
CloseHandle(osReader.hEvent);
return -1;
break;
}
}
else
{
// Error in communications; report it.
SetErrorMessage(GetLastError());
CloseHandle(osReader.hEvent);
return -1;
}
}
CloseHandle(osReader.hEvent);
if(NumberOfBytesToRead != NumberOfBytesReceived)
{
NumberOfBytesToRead = NumberOfBytesReceived;
SetErrorMessage(ERROR_TIMEOUT);
return -1;
}
return 0; //we return here, so the lock object will be destroyed in correct moment, when lock destroyed, it calls unlock
}
The receiving is triggered by WaitEventChar function.
Any help or comments are highly appriciated.
Greetings
Attila

