Skip to content

Commit 62f136c

Browse files
authored
Prevent kani crash during setup for first time (rust-lang#2799)
> Please ensure your PR description includes the following: > 1. A description of how your changes improve Kani. > 2. Some context on the problem you are solving. > 3. A list of issues that are resolved by this PR. > 4. If you had to perform any manual test, please describe them. > > **Make sure you remove this list from the final PR description.** By using the `tar` file as a lock mechanism, we can detect incomplete setups i.e when both `kani's` working directory and the tar file present before setup, we can simply use the local bundle to start setup again. Resolves rust-lang#1545 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.
1 parent ed2df13 commit 62f136c

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ mod cmd;
1616
mod os_hacks;
1717
mod setup;
1818

19-
use std::env;
2019
use std::ffi::OsString;
2120
use std::os::unix::prelude::CommandExt;
2221
use std::path::{Path, PathBuf};
2322
use std::process::Command;
23+
use std::{env, fs};
2424

2525
use anyhow::{bail, Context, Result};
2626

@@ -33,6 +33,15 @@ pub fn proxy(bin: &str) -> Result<()> {
3333
fail_if_in_dev_environment()?;
3434
if !setup::appears_setup() {
3535
setup::setup(None)?;
36+
} else {
37+
// This handles cases where the setup was left incomplete due to an interrupt
38+
// For example - https://github.com/model-checking/kani/issues/1545
39+
if let Some(path_to_bundle) = setup::appears_incomplete() {
40+
setup::setup(Some(path_to_bundle.clone().into_os_string()))?;
41+
// Suppress warning with unused assignment
42+
// and remove the bundle if it still exists
43+
let _ = fs::remove_file(path_to_bundle);
44+
}
3645
}
3746
exec(bin)
3847
}

src/setup.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,22 @@ pub fn appears_setup() -> bool {
5353
kani_dir().expect("couldn't find kani directory").exists()
5454
}
5555

56+
// Ensure that the tar file does not exist, essentially using its presence
57+
// to detect setup completion as if it were a lock file.
58+
pub fn appears_incomplete() -> Option<PathBuf> {
59+
let kani_dir = kani_dir().expect("couldn't find kani directory");
60+
let kani_dir_parent = kani_dir.parent().unwrap();
61+
62+
for entry in std::fs::read_dir(&kani_dir_parent).ok()?.flatten() {
63+
if let Some(file_name) = entry.file_name().to_str() {
64+
if file_name.ends_with(".tar.gz") {
65+
return Some(kani_dir_parent.join(file_name));
66+
}
67+
}
68+
}
69+
None
70+
}
71+
5672
/// Sets up Kani by unpacking/installing to `~/.kani/kani-VERSION`
5773
pub fn setup(use_local_bundle: Option<OsString>) -> Result<()> {
5874
let kani_dir = kani_dir()?;
@@ -92,7 +108,10 @@ fn setup_kani_bundle(kani_dir: &Path, use_local_bundle: Option<OsString>) -> Res
92108
.arg("-zxf")
93109
.arg(&path)
94110
.current_dir(&kani_dir)
95-
.run()?;
111+
.run()
112+
.context(
113+
"Failed to extract tar file, try removing Kani setup located in .kani in your home directory and restarting",
114+
)?;
96115
} else {
97116
let filename = download_filename();
98117
println!("[2/5] Downloading Kani release bundle: {}", &filename);

0 commit comments

Comments
 (0)