Skip to content
Snippets Groups Projects
Commit 2844e365 authored by Federico Lolli's avatar Federico Lolli
Browse files

Fix data race between writing and reading

I think the issue is on taking the mutex for a reading when a writing is enqueued resulting in a deadlock.

has not been tested yet
parent 3e11cd8b
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,7 @@ use std::{
Arc,
},
thread::{self, JoinHandle},
time::Duration,
time::{Duration, Instant},
};
use hashbrown::HashMap;
......@@ -26,6 +26,8 @@ struct SerialQueue {
_handle: JoinHandle<()>,
sender: Sender<Vec<u8>>,
serial: Arc<Mutex<Box<dyn SerialPort>>>,
/// this the timeout after which it returns a timeout error
read_timeout: Duration,
}
impl SerialManager {
......@@ -60,13 +62,20 @@ impl SerialManager {
let port = map.get(name).ok_or(Error::SerialNotOpen)?;
let mut buf = vec![0; n];
// implement a read exact to allow better error messages
let mut reader = port.lock();
let mut filled = 0;
let start = Instant::now();
while filled < n {
let mut reader = port.lock();
match reader.read(&mut buf[filled..]) {
Ok(n) => filled += n,
Err(e) => match e.kind() {
std::io::ErrorKind::TimedOut => {
// if timeout hasn't been reached yet
if start.elapsed() < port.read_timeout {
continue; // this triggers a waiting mutex on the writing side
}
// otherwise
if filled == 0 {
return Err(Error::NoDataAvailable);
}
......@@ -103,9 +112,10 @@ impl SerialQueue {
/// Open the serial port and start a thread to write data as soon as it is
/// available (by using a channel)
fn open(port: &str, baudrate: u32) -> SResult<Self> {
let read_waiting_interval = Duration::from_millis(50);
let serial = Arc::new(Mutex::new(
serialport::new(port, baudrate)
.timeout(Duration::from_millis(1000))
.timeout(read_waiting_interval)
.open()?,
));
let (tx, rx) = channel::<Vec<u8>>();
......@@ -119,6 +129,7 @@ impl SerialQueue {
_handle,
sender: tx,
serial,
read_timeout: Duration::from_millis(1000),
})
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment