-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix serial read for windows #190
base: develop
Are you sure you want to change the base?
Conversation
If serial buffer contained more values than requested by erpc underlying receive `serial_read` got stuck.
{ | ||
do | ||
{ | ||
|
||
ClearCommError(hCom, &errors, NULL); | ||
|
||
if (!ReadFile(hCom, temp, RX_BUF_BYTES - bytesToRead, &bytesRead, &s_readOverlap)) | ||
if (!ReadFile(hCom, temp, size - totalBytesRead, &bytesRead, &s_readOverlap)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like what the original code was trying to do is read size
bytes and size
may be larger than RX_BUF_BYTES
. When size > RX_BUF_BYTES
it is necessary to call ReadFile
multiple times. It seems to me like the bytesToRead
variable is named badly. I don't really know the details of the Windows serial API, but to me, it seems like the overall flow should be something like this:
char temp[RX_BUF_BYTES];
size_t totalBytesRead = 0;
while (totalBytesRead < size) {
const DWORD bytesToRead = std::min(RX_BUF_BYTES, size - totalBytesRead);
DWORD bytesRead;
if (!ReadFile(hCom, temp, bytesToRead, &bytesRead, &s_readOverlap)) {
// TODO: error handling
}
if (bytesRead == 0) {
// TODO: can this happen?
}
memcpy(&buf[totalBytesRead], temp, bytesRead);
totalBytesRead += bytesRead;
}
return totalBytesRead;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem with the original implementation was that:
if (!ReadFile(hCom, temp, RX_BUF_BYTES - bytesToRead, &bytesRead, &s_readOverlap))
leads to reading all bytes which were in the RX buffer. However, erpc tries to read at first 4 bytes then should return and tries to read the remaining bytes in another call to serial_read
. So the original implementation got stuck when it read more than 4 bytes because this loop:
while (bytesToRead != size)
was never exited due to bytesToRead
(naming is really confusing, so I changed it) got bigger than size
.
Changing the implementation to
if (!ReadFile(hCom, temp, size - totalBytesRead, &bytesRead, &s_readOverlap))
ensures that only the desired amount of data is being retrieved from the buffer.
Cosnidering you proposal:
if (bytesRead == 0) {
// TODO: can this happen?
}
yes this can happen, and the loop should continue until it has read the desired amount of data.
For this snippet:
if (!ReadFile(hCom, temp, bytesToRead, &bytesRead, &s_readOverlap)) {
// TODO: error handling
}
My aim wasn't to improve error handling and therefore would keep what is implemented, i.e.
{
if (GetLastError() == ERROR_IO_PENDING)
{
if (!GetOverlappedResult(hCom, &s_readOverlap, &bytesRead, FALSE))
{
bytesRead = 0;
totalBytesRead = 0;
}
}
else
{
bytesRead = 0;
totalBytesRead = 0;
}
}
else
{
bytesRead = 0;
totalBytesRead = 0;
}
}
Thank you @aelray for providing this PR and the detailed description. These changes seems to be reasonable but the internal testing for the v1.8.1 release is almost finished, I would rather integrate this PR after the release, i.e. in about 3w, ok? Thank you. |
Hi @aelray , as see in Copyright we are not authors of this file. I actually don't know from where this file was took. Any chance to found original code based on Copyright and see their fix if any was done? |
There is the same issue ReadFile |
If serial buffer contained more values than requested by erpc
underlying_receive
serial_read
got stuck.