Merge "Fix race between read/write" into main
diff --git a/microdroid_manager/src/ioutil.rs b/microdroid_manager/src/ioutil.rs
index d36e349..772941d 100644
--- a/microdroid_manager/src/ioutil.rs
+++ b/microdroid_manager/src/ioutil.rs
@@ -28,6 +28,10 @@
const SLEEP_DURATION: Duration = Duration::from_millis(5);
/// waits for a file with a timeout and returns it
+///
+/// WARNING: This only guarantees file creation. When there's another thread
+/// writing a file and you're waiting for the file, reading the file should be
+/// synchronized with other mechanism than just waiting for the creation.
pub fn wait_for_file<P: AsRef<Path> + Debug>(path: P, timeout: Duration) -> Result<File> {
debug!("waiting for {:?}...", path);
let begin = Instant::now();
@@ -64,15 +68,21 @@
#[cfg(test)]
mod tests {
use super::*;
+ use std::fs::rename;
use std::io::{Read, Write};
#[test]
fn test_wait_for_file() -> Result<()> {
let test_dir = tempfile::TempDir::new().unwrap();
let test_file = test_dir.path().join("test.txt");
+ let temp_file = test_dir.path().join("test.txt~");
thread::spawn(move || -> io::Result<()> {
+ // Sleep to ensure that `wait_for_file` actually waits
thread::sleep(Duration::from_secs(1));
- File::create(test_file)?.write_all(b"test")
+ // Write to a temp file and then rename it to avoid the race between
+ // write and read.
+ File::create(&temp_file)?.write_all(b"test")?;
+ rename(temp_file, test_file)
});
let test_file = test_dir.path().join("test.txt");