Skip to content

Commit

Permalink
Merge pull request #100 from jfrimmel/cleanup
Browse files Browse the repository at this point in the history
Some code cleanup
  • Loading branch information
jfrimmel authored Sep 22, 2024
2 parents 3084430 + 66cd2b7 commit 8e1c319
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 91 deletions.
88 changes: 8 additions & 80 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,79 +18,17 @@
)]

mod driver;
mod output;
mod panic;
mod valgrind;

use colored::Colorize as _;
use std::env;
use std::process;

/// Nicely format the errors in the valgrind output, if there are any.
fn display_errors(errors: &[valgrind::xml::Error]) {
// format the output in a helpful manner
for error in errors {
if error.kind.is_leak() {
display_leak(error);
} else {
display_generic_error(error);
}
}

let total: usize = errors.iter().map(|error| error.resources.bytes).sum();
eprintln!(
"{:>12} Leaked {} total ({} other errors)",
"Summary".red().bold(),
bytesize::to_string(total as _, true),
errors.iter().filter(|e| !e.kind.is_leak()).count()
);
}

/// Nicely format a single memory leak error.
fn display_leak(error: &valgrind::xml::Error) {
eprintln!(
"{:>12} leaked {} in {} block{}",
"Error".red().bold(),
bytesize::to_string(error.resources.bytes as _, true),
error.resources.blocks,
if error.resources.blocks == 1 { "" } else { "s" }
);

let stack = &error.stack_trace[0]; // always available
display_stack_trace("stack trace (user code at the bottom)", stack);
}

/// Nicely format a non-memory-leak error.
fn display_generic_error(error: &valgrind::xml::Error) {
eprintln!(
"{:>12} {}",
"Error".red().bold(),
error.main_info.as_ref().map_or("unknown", String::as_str)
);

let stack = &error.stack_trace[0]; // always available
display_stack_trace("main stack trace (user code at the bottom)", stack);
error
.stack_trace
.iter()
.skip(1)
.enumerate()
.map(|(index, stack)| (error.auxiliary_info.get(index), stack))
.for_each(|(msg, stack)| {
display_stack_trace(
msg.map_or_else(|| "additional stack trace", String::as_str),
stack,
);
});
}

/// Write out the full stack trace (indented to match other messages).
fn display_stack_trace(msg: &str, stack: &valgrind::xml::Stack) {
eprintln!("{:>12} {}", "Info".cyan().bold(), msg);
stack
.frames
.iter()
.for_each(|frame| eprintln!(" at {frame}"));
}
/// Part of the output message of `valgrind` if a possible stack overflow is
/// detected.
const STACK_OVERFLOW: &str = "main thread stack using the --main-stacksize= flag";

fn main() {
panic::replace_hook();
Expand Down Expand Up @@ -134,23 +72,13 @@ fn main() {
errors: Some(errors),
..
}) => {
display_errors(&errors);
output::display_errors(&errors);
127
}
Ok(_) => 0,
Err(e @ valgrind::Error::MalformedOutput(..)) => {
panic_with!(e);
}
Err(valgrind::Error::ValgrindFailure(output))
if output.contains("main thread stack using the --main-stacksize= flag") =>
{
let error = "Error".red().bold();
let info = "Info".cyan().bold();
eprintln!("{error:>12}: looks like the program overflowed its stack");
eprintln!("{info:>12}: valgrind says:");
output
.lines()
.for_each(|line| eprintln!(" {line}"));
Err(e @ valgrind::Error::MalformedOutput(..)) => std::panic::panic_any(e), // the panic handler catches this and reports it appropriately
Err(valgrind::Error::ValgrindFailure(output)) if output.contains(STACK_OVERFLOW) => {
output::display_stack_overflow(&output);
134 // default exit code for stack overflows
}
Err(e) => {
Expand Down
81 changes: 81 additions & 0 deletions src/output.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//! Write human-readable and colored output the the console.
use crate::valgrind;
use colored::Colorize as _;

/// Nicely format the errors in the valgrind output, if there are any.
pub fn display_errors(errors: &[valgrind::xml::Error]) {
// format the output in a helpful manner
for error in errors {
if error.kind.is_leak() {
display_leak(error);
} else {
display_generic_error(error);
}
}

let total: usize = errors.iter().map(|error| error.resources.bytes).sum();
eprintln!(
"{:>12} Leaked {} total ({} other errors)",
"Summary".red().bold(),
bytesize::to_string(total as _, true),
errors.iter().filter(|e| !e.kind.is_leak()).count()
);
}

/// Nicely format a single memory leak error.
fn display_leak(error: &valgrind::xml::Error) {
eprintln!(
"{:>12} leaked {} in {} block{}",
"Error".red().bold(),
bytesize::to_string(error.resources.bytes as _, true),
error.resources.blocks,
if error.resources.blocks == 1 { "" } else { "s" }
);

let stack = &error.stack_trace[0]; // always available
display_stack_trace("stack trace (user code at the bottom)", stack);
}

/// Nicely format a non-memory-leak error.
fn display_generic_error(error: &valgrind::xml::Error) {
eprintln!(
"{:>12} {}",
"Error".red().bold(),
error.main_info.as_ref().map_or("unknown", String::as_str)
);

let stack = &error.stack_trace[0]; // always available
display_stack_trace("main stack trace (user code at the bottom)", stack);
error
.stack_trace
.iter()
.skip(1)
.enumerate()
.map(|(index, stack)| (error.auxiliary_info.get(index), stack))
.for_each(|(msg, stack)| {
display_stack_trace(
msg.map_or_else(|| "additional stack trace", String::as_str),
stack,
);
});
}

/// Write out the full stack trace (indented to match other messages).
fn display_stack_trace(msg: &str, stack: &valgrind::xml::Stack) {
eprintln!("{:>12} {}", "Info".cyan().bold(), msg);
stack
.frames
.iter()
.for_each(|frame| eprintln!(" at {frame}"));
}

/// Write out an error message for describing the stack overflow message.
pub fn display_stack_overflow(output: &str) {
let error = "Error".red().bold();
let info = "Info".cyan().bold();
eprintln!("{error:>12}: looks like the program overflowed its stack");
eprintln!("{info:>12}: valgrind says:");
output
.lines()
.for_each(|line| eprintln!(" {line}"));
}
11 changes: 0 additions & 11 deletions src/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,6 @@ const PANIC_HEADER: &str = "
how to reproduce it.
";

/// Panic with a custom panic output.
///
/// This is helpful for printing debug information to the panic message.
#[macro_export]
#[allow(clippy::module_name_repetitions)] // necessary for exported macro
macro_rules! panic_with {
($e:expr) => {
std::panic::panic_any($e)
};
}

/// Replaces any previous hook with the custom hook of this application.
///
/// This custom hook points the user to the project repository and asks them to
Expand Down

0 comments on commit 8e1c319

Please sign in to comment.