PTLib 2.18.8 release bundle on Linux arm, kernel 3.18.20, glibc 2.21.
In src/ptlib/unix/channel.cxx, PChannel::Read() method, which PSerialChannel::Read() inherits unchanged, contains the following code:
...
PPROFILE_SYSTEM(
int result = ::read(os_handle, buf, len);
);
if (result >= 0)
return ConvertOSError(SetLastReadCount(result), LastReadError) && result > 0;
switch (errno) {
...
case EWOULDBLOCK :
if (readTimeout > 0) {
if (PXSetIOBlock(PXReadBlock, readTimeout))
break;
return false;
}
...
Serial devices in PTLib are opened with O_NONBLOCK flag, so the expected behaviour is when there's no data from the serial port yet, read() call would return (-1) and set errno to EWOULDBLOCK.
But, in fact, there are serial devices (I wouldn't state this for the whole world) returning 0 from read() and errno is also 0 despite of O_NONBLOCK set, so in case when no data to read, PSerialChannel::Read() returns immediately disregarding SetReadTimeout() value, and it breaks existing application functionality.
In old PWLib 1.10.0, for example (I didn't dive deep into the revision history), PXSetIOBlock() was called before read():
...
if (!PXSetIOBlock(PXReadBlock, readTimeout))
return FALSE;
if (ConvertOSError(lastReadCount = ::read(os_handle, buf, len), LastReadError))
return lastReadCount > 0;
...
... and it worked properly.
Suggested solution:
Revert this peace of code to call PXSetIOBlock() before read().