No such a file or directory even Path.is_file true

I want to remove a db file if it exists when running test cases. So I tried below code but it is failing. Can you give me possible reasons to this error?

let db_path = Path::new("./tmp/data/data.mdb"); 

if db_path.is_file() {
    dbg!(db_path.exists()); // db_path.exists() = true
    dbg!(db_path.is_file()); // db_path.is_file() = true
    dbg!(std::fs::metadata(db_path));
    // Ok(
    // Metadata {
    //     file_type: FileType(
    //         FileType {
    //             mode: 33152,
    //         },
    //     ),
    //     is_dir: false,
    //     is_file: true,
    //     permissions: Permissions(
    //         FilePermissions {
    //             mode: 33152,
    //         },
    //     ),
    //     modified: Ok(
    //         SystemTime {
    //             tv_sec: 1647472466,
    //             tv_nsec: 574985772,
    //         },
    //     ),
    //     accessed: Ok(
    //         SystemTime {
    //             tv_sec: 1647472466,
    //             tv_nsec: 274984150,
    //         },
    //     ),
    //     created: Ok(
    //         SystemTime {
    //             tv_sec: 1647472466,
    //             tv_nsec: 274984150,
    //         },
    //     ),
    //     ..
    // },
    std::fs::remove_file(db_path).unwrap(); // thread 'app::standalone_tests::test_db_created' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }'
}

Upvotes: 2

Views: 1488

Answers (1)

Silvio Mayolo
Silvio Mayolo

Reputation: 70297

Since you mention test cases, Rust runs its tests in parallel by default. So one thread is probably deleting the file while another thread is in between its is_file and remove_file lines, leading to a race condition. The code sequence of "check whether file exists, then delete it" should be considered a critical code path and should be locked behind a mutex or some other kind of thread-safety mechanism.

Alternatively, you can pass command line flags to run tests in sequence and only use one thread, but this is probably not a good long-term solution.

Upvotes: 5

Related Questions