From 7439aeb63ef692510c121a0e9f090d58de8d87e2 Mon Sep 17 00:00:00 2001 From: BlackDex Date: Tue, 25 Feb 2020 14:10:52 +0100 Subject: [PATCH 1/2] Make panics logable (as warn) panic!()'s only appear on stderr, this makes tracking down some strange issues harder with the usage of docker since stderr does not get logged into the bitwarden.log file. This change logs the message to stdout and the logfile when activated. --- src/main.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main.rs b/src/main.rs index 7c9d026..3e2a9e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,7 @@ use std::{ path::Path, process::{exit, Command}, str::FromStr, + panic, }; #[macro_use] @@ -121,6 +122,11 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { logger.apply()?; + // Catch panics and log them instead of default output to StdErr + panic::set_hook(Box::new(|info| { + warn!("[PANIC] {}", info); + })); + Ok(()) } From bd09fe1a3d9b7f31644fb5fb9f9c38a30c893dac Mon Sep 17 00:00:00 2001 From: BlackDex Date: Mon, 16 Mar 2020 17:53:22 +0100 Subject: [PATCH 2/2] Updated code so backtraces are logged also. --- Cargo.lock | 1 + Cargo.toml | 3 +++ src/main.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f0b516..160ce90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,6 +119,7 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" name = "bitwarden_rs" version = "1.0.0" dependencies = [ + "backtrace", "chashmap", "chrono", "data-encoding", diff --git a/Cargo.toml b/Cargo.toml index bdd9385..e8187fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,6 +118,9 @@ idna = "0.2.0" # CLI argument parsing structopt = "0.3.11" +# Logging panics to logfile instead stderr only +backtrace = "0.3.45" + [patch.crates-io] # Use newest ring rocket = { git = 'https://github.com/SergioBenitez/Rocket', rev = 'b95b6765e1cc8be7c1e7eaef8a9d9ad940b0ac13' } diff --git a/src/main.rs b/src/main.rs index aeda5ba..a8efb1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,12 +20,14 @@ extern crate derive_more; #[macro_use] extern crate num_derive; +extern crate backtrace; + use std::{ fs::create_dir_all, path::Path, process::{exit, Command}, str::FromStr, - panic, + panic, thread, fmt // For panic logging }; #[macro_use] @@ -43,6 +45,16 @@ pub use error::{Error, MapResult}; use structopt::StructOpt; +// Used for catching panics and log them to file instead of stderr +use backtrace::Backtrace; +struct Shim(Backtrace); + +impl fmt::Debug for Shim { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + write!(fmt, "\n{:?}", self.0) + } +} + #[derive(Debug, StructOpt)] #[structopt(name = "bitwarden_rs", about = "A Bitwarden API server written in Rust")] struct Opt { @@ -145,7 +157,40 @@ fn init_logging(level: log::LevelFilter) -> Result<(), fern::InitError> { // Catch panics and log them instead of default output to StdErr panic::set_hook(Box::new(|info| { - warn!("[PANIC] {}", info); + let backtrace = Backtrace::new(); + + let thread = thread::current(); + let thread = thread.name().unwrap_or("unnamed"); + + let msg = match info.payload().downcast_ref::<&'static str>() { + Some(s) => *s, + None => match info.payload().downcast_ref::() { + Some(s) => &**s, + None => "Box", + }, + }; + + match info.location() { + Some(location) => { + error!( + target: "panic", "thread '{}' panicked at '{}': {}:{}{:?}", + thread, + msg, + location.file(), + location.line(), + Shim(backtrace) + ); + } + None => { + error!( + target: "panic", + "thread '{}' panicked at '{}'{:?}", + thread, + msg, + Shim(backtrace) + ) + } + } })); Ok(())