Adding the ctrlc crate to Cargo.toml with the termination feature, I tested the code below.
I compiled with cargo build and then run it by double clicking the executable. Then, when the console spawns, click the X Close button.
With the ctrlc version, the code didn't work as expected. I expected, after closing the console, for both the X.txt and m_X.txt to keep being saved every second, for 5 seconds. However, when I clicked close, they both stop printing right away. The ctrl handler only prints a single file, m_1.txt.
I managed to get it work properly with the winapi version, commented in the code below. To test that, just comment the ctrlc code and uncommented that one.
What am I doing wrong?
main.rs
use ctrlc;
use std::fs::File;
use std::io::Write;
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use std::{thread, time::Duration};
use winapi::shared::minwindef::{BOOL, TRUE};
use winapi::um::consoleapi::SetConsoleCtrlHandler; // SetConsoleCtrlHandler is in consoleapi module
//============================ rust-ctrlc version =======================================
fn register_ctrl_handler(exit_flag: Arc<AtomicBool>) {
ctrlc::set_handler(move || {
let handler_start_time = std::time::Instant::now();
for _ in 0..30 {
let elapsed_secs = handler_start_time.elapsed().as_secs();
let file_name = format!("m_{}.txt", elapsed_secs);
File::create(&file_name);
thread::sleep(Duration::from_secs(1));
}
exit_flag.store(true, Ordering::SeqCst);
println!("Handler finished execution.");
})
.expect("Error setting up CTRL+C handler");
}
fn main() {
let start_time = std::time::Instant::now();
let exit_flag = Arc::new(AtomicBool::new(false));
register_ctrl_handler(Arc::clone(&exit_flag));
while !exit_flag.load(Ordering::SeqCst) {
let elapsed_secs = start_time.elapsed().as_secs();
let file_name = format!("{}.txt", elapsed_secs);
let mut file = File::create(&file_name).expect("Unable to create file");
writeln!(file, "Elapsed seconds: {}", elapsed_secs).expect("Unable to write to file");
println!("Saved file: {}", file_name);
thread::sleep(Duration::from_secs(1));
}
println!("Program exited gracefully.");
}
// ==================================== WINAPI version =======================================
// unsafe extern "system" fn ctrl_handler(_ctrl_type: u32) -> BOOL {
// println!("CTRL+C detected. Handler started...");
// let handler_start_time = std::time::Instant::now();
// for i in 0..30 {
// let elapsed_secs = handler_start_time.elapsed().as_secs();
// let file_name = format!("m_{}.txt", elapsed_secs);
// File::create(&file_name);
// thread::sleep(Duration::from_secs(1));
// }
// println!("Handler finished execution.");
// TRUE
// }
// fn register_ctrl_handler(_exit_flag: Arc<AtomicBool>) {
// unsafe {
// if SetConsoleCtrlHandler(Some(ctrl_handler), TRUE) == 0 {
// panic!("Error setting up CTRL+C handler");
// }
// }
// }
// fn main() {
// let start_time = std::time::Instant::now();
// let exit_flag = Arc::new(AtomicBool::new(false));
// register_ctrl_handler(Arc::clone(&exit_flag));
// while !exit_flag.load(Ordering::SeqCst) {
// let elapsed_secs = start_time.elapsed().as_secs();
// let file_name = format!("{}.txt", elapsed_secs);
// let mut file = File::create(&file_name).expect("Unable to create file");
// writeln!(file, "Elapsed seconds: {}", elapsed_secs).expect("Unable to write to file");
// println!("Saved file: {}", file_name);
// thread::sleep(Duration::from_secs(1));
// }
// println!("Program exited gracefully.");
// }
Cargo.toml
[package]
name = "rust-thread"
version = "0.1.0"
edition = "2021"
[dependencies]
winapi ={version = "*", features = ["wincon", "minwindef", "consoleapi"]}
ctrlc = { version = "*", features = ["termination"] }
Adding the
ctrlccrate toCargo.tomlwith theterminationfeature, I tested the code below.I compiled with
cargo buildand then run it by double clicking the executable. Then, when the console spawns, click the X Close button.With the
ctrlcversion, the code didn't work as expected. I expected, after closing the console, for both theX.txtandm_X.txtto keep being saved every second, for 5 seconds. However, when I clicked close, they both stop printing right away. The ctrl handler only prints a single file,m_1.txt.I managed to get it work properly with the
winapiversion, commented in the code below. To test that, just comment thectrlccode and uncommented that one.What am I doing wrong?
main.rs
Cargo.toml