From fdb92d4746156f6cb6c60d89ad51d38a5f2a2cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beat=20K=C3=BCng?= Date: Fri, 13 Aug 2021 14:17:03 +0200 Subject: [PATCH] protocol_splitter: check available bytes before read() This is to avoid blocking in any case. If we don't do that, ioctl() may signal data available while the other protocol does a read(), and when the first protocol tries to do a read(), it would not have data anymore and would block (so this avoids a race condition). --- src/drivers/protocol_splitter/protocol_splitter.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/drivers/protocol_splitter/protocol_splitter.cpp b/src/drivers/protocol_splitter/protocol_splitter.cpp index 705342dff5..017cf0cb16 100644 --- a/src/drivers/protocol_splitter/protocol_splitter.cpp +++ b/src/drivers/protocol_splitter/protocol_splitter.cpp @@ -160,9 +160,15 @@ int ReadBuffer::read(int fd) PX4_DEBUG("Buffer full: %zu %zu %zu %zu", start_mavlink, end_mavlink, start_rtps, end_rtps); } - int r = ::read(fd, buffer + buf_size, sizeof(buffer) - buf_size); + int bytes_available = 0; + int err = ::ioctl(fd, FIONREAD, (unsigned long)&bytes_available); + ssize_t r = 0; - if (r < 0) { + if (err != 0 || bytes_available > 0) { + r = ::read(fd, buffer + buf_size, sizeof(buffer) - buf_size); + } + + if (r <= 0) { return r; }