Skip to content

Commit

Permalink
Fix deadlock with Driver::write
Browse files Browse the repository at this point in the history
Use a spin lock to recheck the queue size until it has room to push.
  • Loading branch information
kschwarz-intrepidcs committed Aug 14, 2020
1 parent afda617 commit 4cd897b
Show file tree
Hide file tree
Showing 6 changed files with 2 additions and 13 deletions.
4 changes: 2 additions & 2 deletions communication/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ bool Driver::write(const std::vector<uint8_t>& bytes) {
}

if(writeBlocks) {
std::unique_lock<std::mutex> lk(writeMutex);
if(writeQueue.size_approx() > writeQueueSize)
writeCV.wait(lk);
while(writeQueue.size_approx() > (writeQueueSize * 3 / 4))
std::this_thread::sleep_for(std::chrono::milliseconds(10));
} else {
if(writeQueue.size_approx() > writeQueueSize) {
report(APIEvent::Type::TransmitBufferFull, APIEvent::Severity::Error);
Expand Down
6 changes: 0 additions & 6 deletions include/icsneo/communication/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ class Driver {
virtual bool read(std::vector<uint8_t>& bytes, size_t limit = 0);
virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0);
virtual bool write(const std::vector<uint8_t>& bytes);
inline void onWrite() {
if(writeQueue.size_approx() < (writeQueueSize * 3/4))
writeCV.notify_one();
}

device_eventhandler_t report;

Expand All @@ -47,8 +43,6 @@ class Driver {
virtual void writeTask() = 0;
moodycamel::BlockingConcurrentQueue<uint8_t> readQueue;
moodycamel::BlockingConcurrentQueue<WriteOperation> writeQueue;
std::mutex writeMutex;
std::condition_variable writeCV;
std::thread readThread, writeThread;
std::atomic<bool> closing{false};
};
Expand Down
1 change: 0 additions & 1 deletion platform/posix/ftdi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,5 @@ void FTDI::writeTask() {
continue;

ftdi.write(writeOp.bytes.data(), (int)writeOp.bytes.size());

This comment has been minimized.

Copy link
@tysonite

tysonite Sep 1, 2020

I hope, handling of ftdi.write() return code can be handled as I did in #17 (comment). This helps in debugging.

The same applies to ftdi.read() call.

This comment has been minimized.

Copy link
@kschwarz-intrepidcs

kschwarz-intrepidcs Sep 1, 2020

Author Collaborator

We reported the issue to libftdi (http://developer.intra2net.com/mailarchive/html/libftdi/2020/msg00066.html), but we'll provide a patch soon if they don't handle it upstream.

This comment has been minimized.

Copy link
@hollinsky-intrepid

hollinsky-intrepid Sep 1, 2020

Contributor

We'll get the error checking added regardless so you know if errors are occurring, though likely we'll only be able to throw a generic icsneo::APIEvent::FailedToRead or icsneo::APIEvent::FailedToWrite.

This comment has been minimized.

Copy link
@tysonite

tysonite Sep 1, 2020

Alright, thanks for information. I meant to say, there are other potential errors (might be unrecoverable in opposite to timeouts) that might be makes sense to log and report to the user inside libicsneo code. Now error code (return value) is ignored completely.

This comment has been minimized.

Copy link
@hollinsky-intrepid

hollinsky-intrepid Sep 1, 2020

Contributor

Absolutely, there definitely should be a warning there at very least

This comment has been minimized.

Copy link
@tysonite

tysonite Sep 1, 2020

@hollinsky, Thanks, I haven't seen your comment when I wrote previous one.

onWrite();
}
}
1 change: 0 additions & 1 deletion platform/posix/stm32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,5 @@ void STM32::writeTask() {
ssize_t actualWritten = ::write(fd, writeOp.bytes.data(), writeSize);
if(actualWritten != writeSize)
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
onWrite();
}
}
1 change: 0 additions & 1 deletion platform/windows/pcap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ void PCAP::writeTask() {
auto bs = sendPacket.getBytestream();
if(!closing)
pcap.sendpacket(interface.fp, bs.data(), (int)bs.size());
onWrite();
// TODO Handle packet send errors
}
}
Expand Down
2 changes: 0 additions & 2 deletions platform/windows/vcp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,6 @@ void VCP::writeTask() {
bytesWritten = 0;
if(WriteFile(handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &overlappedWrite))
continue;

onWrite();

auto winerr = GetLastError();
if(winerr == ERROR_IO_PENDING) {
Expand Down

1 comment on commit 4cd897b

@kschwarz-intrepidcs
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should address part of #17.

Please sign in to comment.