Reputation: 23
I am maintaining a MFC program which can send data from computer A to computer B through RS232. Sometimes it transmits data smoothly, but sometimes it hangs forever. There are two threads sending the same data to a com port in sequence. The first thread sends data successfully, but the second thread hangs at the code "WriteFile". When the second thread on computer A hangs at "WriteFile", I send some meaningless data like "1" from computer B back to computer A. Then the hanging at "WriteFile" on computer A stop hanging, and computer B finally see the data sent by the second thread on computer A.
Here is the RS232 log from computer B .
The picture shows that two threads on computer A initiate there own test and send messages back to computer B. Each thread complete there own test and send TEST_DONE to computer B almost at the same time. But computer B only see the TEST_DONE sent by first thread on computer A(The second thread is hanging at WriteFile at this point.) until I manually send "1" to computer A from computer B.
Here is my code sending message from computer A to computer B. The length of cmd is 255.
BOOL SerialPort::AutoHandlerRES(unsigned char* cmd){
while(wait_transfer.IsLocked())
Sleep(1000);
wait_transfer.Lock();
CString out;
BOOL RetB;
UCHAR EndChar[2]={0x0D,0x0A};
out=CString(cmd);
DWORD num = out.GetLength()+2;
cmd[num-2]=EndChar[0];
cmd[num-1]=EndChar[1];
RetB=WriteFile(this->m_hCom, cmd, num, &num, NULL);
Sleep(1000);
wait_transfer.Unlock();
return RetB;}
My question is what could be the possible cause causing thread B hanging at "WriteFile"? Why the hanging does not happen on thread A? Thank you!
Upvotes: 1
Views: 1067
Reputation: 6145
From the MSDN page about serial communications :
If one thread is blocked waiting for its I/O operation to complete, all other threads that subsequently call a communications API will be blocked until the original operation completes. For instance, if one thread were waiting for a ReadFile function to return, any other thread that issued a WriteFile function would be blocked.
You probably issue a blocking ReadFile
that prevent the WriteFile
from completing. In your case it would be a race condition between threads ; the writes usually complete before the read is called, but not always.
The best way to prevent this would be to not call the ReadFile
carelessly, but instead wrap it in the same lock as the writes, and wait on the receive COMM event before reading. The raw Win32 calls for that are SetCommMask
and WaitCommEvent
. You can then use ClearCommError
to detect how many bytes should be read (because a receive event doesn't tell you how much data was received).
You can also use overlapped IO to allow simultaneous IO. I find it cleaner, but it's not simpler.
Upvotes: 1