有没有办法做到这一点?在终端图形库中,如果发生异常,异常将在显示之前被刷新,这使得编程很难使用此库进行调试。
impl Drop for Terminal {
fn drop(&mut self) {
self.outbuffer.write_all(&self.driver.get(DevFn::ShowCursor)).unwrap();
self.outbuffer.write_all(&self.driver.get(DevFn::Reset)).unwrap();
self.outbuffer.write_all(&self.driver.get(DevFn::Clear)).unwrap();
self.outbuffer.write_all(&self.driver.get(DevFn::ExitCa)).unwrap();
self.flush().unwrap(); // If an exception occurs, this will reclear the screen and remove the output
self.termctl.reset().unwrap();
SIGWINCH_STATUS.store(false, Ordering::SeqCst);
RUSTTY_STATUS.store(false, Ordering::SeqCst);
}
}
如果我要注释掉self.flush().unwrap();
,则会打印异常,但是即使程序结束,终端也无法正确刷新屏幕并在终端上显示图形。
是否有可能在程序开始时指定用于写入的自定义缓冲区恐慌?或者可能写一个hacky技巧来做到这一点?这样,在刷新之后,我们可以检查是否有任何内容在此缓冲区内,如果是这样,我们就知道发生了异常并且可以将其打印出来。
然而,通过评论self.flush().unwrap();
,我们受到了实际例外的欢迎,但现在是一个非常难看的终端。此解决方案将无法正常执行仍需要刷新的程序,因为不需要显示错误
答案 0 :(得分:3)
恐慌消息当前写入stderr,因此执行此操作的方法是将stderr重定向到文件(cargo run 2>/path/to/panic.log
)。
或者,您可以使用gag在您的程序中执行此操作(免责声明,我编写了此库)。不幸的是,它无法在Windows上运行。
以下内容将重定向stderr,直到stderr_redirect
被删除:
use std::fs::OpenOptions;
use gag::Redirect;
let log = OpenOptions::new()
.truncate(true)
.read(true)
.create(true)
.write(true)
.open("/path/to/panic.log")
.unwrap();
let stderr_redirect = Redirect::stderr(log).unwrap();
// Your code here...
您还可以通过执行以下操作来缓冲临时文件中的stderr:
use gag::BufferRedirect;
let mut stderr_buffer = BufferRedirect::stderr().unwrap();
答案 1 :(得分:0)
您需要向std::panic::set_hook
注册一个 panic hook 来捕获输出。然后,您可以通过std::panic::catch_unwind
惊慌失措:
use std::{
panic,
sync::{Arc, Mutex},
};
fn main() {
let global_buffer = Arc::new(Mutex::new(String::new()));
let old_hook = panic::take_hook();
panic::set_hook({
let global_buffer = global_buffer.clone();
Box::new(move |info| {
let mut global_buffer = global_buffer.lock().unwrap();
if let Some(s) = info.payload().downcast_ref::<&str>() {
global_buffer.push_str(s);
}
})
});
let result = panic::catch_unwind(|| {
panic!("test panic");
});
panic::set_hook(old_hook);
match result {
Ok(res) => res,
Err(_) => {
println!("caught panic!");
println!("I captured:\n\n{}", global_buffer.lock().unwrap())
}
}
}
另请参阅: