Skip to content

Commit 257d7c7

Browse files
jiangliuandreeaflorescu
authored andcommitted
handle ErrorKind::Interrupted when doing file IOs
According to rust doc for Read::read(): If this function encounters any form of I/O or other error, an error variant will be returned. If an error is returned then it must be guaranteed that no bytes were read. An error of the [`ErrorKind::Interrupted`] kind is non-fatal and the read operation should be retried if there is nothing else to do. So we should silently ignore [`ErrorKind::Interrupted`] and retry, otherwise it will false alarms/wrong results. Signed-off-by: Liu Jiang <[email protected]>
1 parent 0934351 commit 257d7c7

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

coverage_config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"coverage_score": 85.7,
2+
"coverage_score": 84.9,
33
"exclude_path": "mmap_windows.rs",
44
"crate_features": "backend-mmap,backend-atomic"
55
}

src/guest_memory.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -743,15 +743,27 @@ impl<T: GuestMemory> Bytes<GuestAddress> for T {
743743
// This is safe cause `start` and `len` are within the `region`.
744744
let start = caddr.raw_value() as usize;
745745
let end = start + len;
746-
let bytes_read = src.read(&mut dst[start..end]).map_err(Error::IOError)?;
747-
Ok(bytes_read)
746+
loop {
747+
match src.read(&mut dst[start..end]) {
748+
Ok(n) => break Ok(n),
749+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
750+
Err(e) => break Err(Error::IOError(e)),
751+
}
752+
}
748753
} else {
749754
let len = std::cmp::min(len, MAX_ACCESS_CHUNK);
750755
let mut buf = vec![0u8; len].into_boxed_slice();
751-
let bytes_read = src.read(&mut buf[..]).map_err(Error::IOError)?;
752-
let bytes_written = region.write(&buf[0..bytes_read], caddr)?;
753-
assert_eq!(bytes_written, bytes_read);
754-
Ok(bytes_read)
756+
loop {
757+
match src.read(&mut buf[..]) {
758+
Ok(bytes_read) => {
759+
let bytes_written = region.write(&buf[0..bytes_read], caddr)?;
760+
assert_eq!(bytes_written, bytes_read);
761+
break Ok(bytes_read);
762+
}
763+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
764+
Err(e) => break Err(Error::IOError(e)),
765+
}
766+
}
755767
}
756768
})
757769
}
@@ -809,12 +821,17 @@ impl<T: GuestMemory> Bytes<GuestAddress> for T {
809821
// This is safe cause `start` and `len` are within the `region`.
810822
let start = caddr.raw_value() as usize;
811823
let end = start + len;
812-
// It is safe to read from volatile memory. Accessing the guest
813-
// memory as a slice should be OK as long as nothing assumes another
814-
// thread won't change what is loaded; however, we may want to introduce
815-
// VolatileRead and VolatileWrite traits in the future.
816-
let bytes_written = dst.write(&src[start..end]).map_err(Error::IOError)?;
817-
Ok(bytes_written)
824+
loop {
825+
// It is safe to read from volatile memory. Accessing the guest
826+
// memory as a slice should be OK as long as nothing assumes another
827+
// thread won't change what is loaded; however, we may want to introduce
828+
// VolatileRead and VolatileWrite traits in the future.
829+
match dst.write(&src[start..end]) {
830+
Ok(n) => break Ok(n),
831+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
832+
Err(e) => break Err(Error::IOError(e)),
833+
}
834+
}
818835
} else {
819836
let len = std::cmp::min(len, MAX_ACCESS_CHUNK);
820837
let mut buf = vec![0u8; len].into_boxed_slice();

src/volatile_memory.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,13 @@ impl Bytes<usize> for VolatileSlice<'_> {
592592
// memory as a mutable slice is OK because nothing assumes another
593593
// thread won't change what is loaded.
594594
let dst = &mut self.as_mut_slice()[addr..end];
595-
src.read(dst).map_err(Error::IOError)
595+
loop {
596+
match src.read(dst) {
597+
Ok(n) => break Ok(n),
598+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
599+
Err(e) => break Err(Error::IOError(e)),
600+
}
601+
}
596602
}
597603
}
598604

@@ -656,7 +662,13 @@ impl Bytes<usize> for VolatileSlice<'_> {
656662
// memory as a slice is OK because nothing assumes another thread
657663
// won't change what is loaded.
658664
let src = &self.as_mut_slice()[addr..end];
659-
dst.write(src).map_err(Error::IOError)
665+
loop {
666+
match dst.write(src) {
667+
Ok(n) => break Ok(n),
668+
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => continue,
669+
Err(e) => break Err(Error::IOError(e)),
670+
}
671+
}
660672
}
661673
}
662674

0 commit comments

Comments
 (0)