Skip to content

Commit b7ae080

Browse files
Improve --jobs UI (#3790)
Improve the documentation for the `--jobs` option, change it to use `hide_short_help` like other unstable options, and print the current thread number so that users can match the harness to its output. Example: ```rust #[kani::modifies(x)] #[kani::ensures(|_| x.iter().map(|v| *v == 0).fold(true,|a,b|a&b))] fn zero(x: &mut [u8]) { x.fill(0) } #[kani::proof_for_contract(zero)] fn harness() { let mut x = [kani::any(), kani::any(), kani::any()]; zero(&mut x); } #[kani::proof] fn harness_2() { assert!(true); } #[kani::proof] fn harness_3() { assert!(false); } ``` ``` cargo kani -j --enable-unstable --output-format=terse -Z function-contracts Kani Rust Verifier 0.57.0 (cargo plugin) warning: Found the following unsupported constructs: - caller_location (1) - foreign function (1) Verification will fail if one or more of these constructs is reachable. See https://model-checking.github.io/kani/rust-feature-support.html for more details. Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s Thread 4: Checking harness harness_2... Thread 2: Checking harness harness_3... Thread 4: VERIFICATION RESULT: ** 0 of 1 failed VERIFICATION:- SUCCESSFUL Verification Time: 0.0137195s Thread 2: VERIFICATION RESULT: ** 1 of 1 failed Failed Checks: assertion failed: false File: "src/lib.rs", line 26, in harness_3 VERIFICATION:- FAILED Verification Time: 0.012914542s Thread 0: Checking harness harness... Thread 0: VERIFICATION RESULT: ** 0 of 217 failed VERIFICATION:- SUCCESSFUL Verification Time: 18.47224s Summary: Verification failed for - harness_3 Complete - 2 successfully verified harnesses, 1 failures, 3 total. ``` By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: Zyad Hassan <[email protected]>
1 parent 3f5f8e8 commit b7ae080

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

kani-driver/src/args/mod.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,11 @@ pub struct VerificationArgs {
257257
// consumes everything
258258
pub cbmc_args: Vec<OsString>,
259259

260-
/// Number of parallel jobs, defaults to 1
261-
#[arg(short, long, hide = true, requires("enable_unstable"))]
260+
/// Number of threads to spawn to verify harnesses in parallel.
261+
/// Omit the flag entirely to run sequentially (i.e. one thread).
262+
/// Pass -j to run with the thread pool's default number of threads.
263+
/// Pass -j <N> to specify N threads.
264+
#[arg(short, long, hide_short_help = true, requires("enable_unstable"))]
262265
pub jobs: Option<Option<usize>>,
263266

264267
/// Enable extra pointer checks such as invalid pointers in relation operations and pointer

kani-driver/src/harness_runner.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -103,30 +103,48 @@ impl<'pr> HarnessRunner<'_, 'pr> {
103103
}
104104

105105
impl KaniSession {
106-
fn process_output(&self, result: &VerificationResult, harness: &HarnessMetadata) {
106+
fn process_output(
107+
&self,
108+
result: &VerificationResult,
109+
harness: &HarnessMetadata,
110+
thread_index: usize,
111+
) {
107112
if self.should_print_output() {
108113
if self.args.output_into_files {
109-
self.write_output_to_file(result, harness);
114+
self.write_output_to_file(result, harness, thread_index);
110115
}
111116

112117
let output = result.render(&self.args.output_format, harness.attributes.should_panic);
113-
println!("{}", output);
118+
if rayon::current_num_threads() > 1 {
119+
println!("Thread {thread_index}: {output}");
120+
} else {
121+
println!("{output}");
122+
}
114123
}
115124
}
116125

117126
fn should_print_output(&self) -> bool {
118127
!self.args.common_args.quiet && self.args.output_format != OutputFormat::Old
119128
}
120129

121-
fn write_output_to_file(&self, result: &VerificationResult, harness: &HarnessMetadata) {
130+
fn write_output_to_file(
131+
&self,
132+
result: &VerificationResult,
133+
harness: &HarnessMetadata,
134+
thread_index: usize,
135+
) {
122136
let target_dir = self.result_output_dir().unwrap();
123137
let file_name = target_dir.join(harness.pretty_name.clone());
124138
let path = Path::new(&file_name);
125139
let prefix = path.parent().unwrap();
126140

127141
std::fs::create_dir_all(prefix).unwrap();
128142
let mut file = File::create(&file_name).unwrap();
129-
let file_output = result.render(&OutputFormat::Regular, harness.attributes.should_panic);
143+
let mut file_output =
144+
result.render(&OutputFormat::Regular, harness.attributes.should_panic);
145+
if rayon::current_num_threads() > 1 {
146+
file_output = format!("Thread {thread_index}:\n{file_output}");
147+
}
130148

131149
if let Err(e) = writeln!(file, "{}", file_output) {
132150
eprintln!(
@@ -148,13 +166,18 @@ impl KaniSession {
148166
binary: &Path,
149167
harness: &HarnessMetadata,
150168
) -> Result<VerificationResult> {
169+
let thread_index = rayon::current_thread_index().unwrap_or_default();
151170
if !self.args.common_args.quiet {
152-
println!("Checking harness {}...", harness.pretty_name);
171+
if rayon::current_num_threads() > 1 {
172+
println!("Thread {thread_index}: Checking harness {}...", harness.pretty_name);
173+
} else {
174+
println!("Checking harness {}...", harness.pretty_name);
175+
}
153176
}
154177

155178
let mut result = self.with_timer(|| self.run_cbmc(binary, harness), "run_cbmc")?;
156179

157-
self.process_output(&result, harness);
180+
self.process_output(&result, harness, thread_index);
158181
self.gen_and_add_concrete_playback(harness, &mut result)?;
159182
Ok(result)
160183
}

0 commit comments

Comments
 (0)