Skip to content

Commit

Permalink
Merge pull request #7459 from roc-lang/ayaz/panic-catcher
Browse files Browse the repository at this point in the history
Catch panics that happen within repl step executions
  • Loading branch information
lukewilliamboswell authored Jan 8, 2025
2 parents d0b19b7 + 106089a commit e18b437
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 63 deletions.
6 changes: 0 additions & 6 deletions .github/workflows/ci_manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,11 +124,6 @@ jobs:
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/benchmarks.yml

start-panic-check:
needs: check-changes
if: needs.check-changes.outputs.run_tests == 'full'
uses: ./.github/workflows/improve_panics.yml

ran-full:
runs-on: ubuntu-22.04
needs: [
Expand All @@ -142,7 +137,6 @@ jobs:
start-windows-release-build-test,
start-windows-tests,
start-roc-benchmarks,
start-panic-check
]
steps:
- run: echo "all workflows succeeded!"
Expand Down
56 changes: 0 additions & 56 deletions .github/workflows/improve_panics.yml

This file was deleted.

60 changes: 59 additions & 1 deletion crates/repl_cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ use rustyline::highlight::{Highlighter, PromptInfo};
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
use rustyline::Config;
use rustyline_derive::{Completer, Helper, Hinter};
use std::any::Any;
use std::backtrace::Backtrace;
use std::borrow::Cow;
use std::panic::{AssertUnwindSafe, PanicInfo};
use std::sync::{Arc, Mutex, OnceLock};
use target_lexicon::Triple;

use crate::cli_gen::eval_llvm;
Expand All @@ -37,10 +41,27 @@ pub struct ReplHelper {
state: ReplState,
}

static BACKTRACE: OnceLock<Arc<Mutex<Option<String>>>> = OnceLock::new();

fn init_backtrace_storage() {
BACKTRACE.get_or_init(|| Arc::new(Mutex::new(None)));
}

fn panic_hook(_: &PanicInfo) {
if let Some(storage) = BACKTRACE.get() {
let _ = storage.lock().map(|ref mut storage| {
**storage = Some(Backtrace::force_capture().to_string());
});
}
}

pub fn main(has_color: bool, has_header: bool) -> i32 {
use rustyline::error::ReadlineError;
use rustyline::Editor;

init_backtrace_storage();
std::panic::set_hook(Box::new(panic_hook));

let strip_colors_if_necessary = |s: &str| {
if has_color {
s.to_string()
Expand Down Expand Up @@ -85,7 +106,13 @@ pub fn main(has_color: bool, has_header: bool) -> i32 {
.state;

arena.reset();
match repl_state.step(&arena, line, target, DEFAULT_PALETTE) {

let action = std::panic::catch_unwind(AssertUnwindSafe(|| {
repl_state.step(&arena, line, target, DEFAULT_PALETTE)
}))
.unwrap_or_else(|e| notify_repl_panic(target, e));

match action {
ReplAction::Eval { opt_mono, problems } => {
let output = evaluate(opt_mono, problems, target);
// If there was no output, don't print a blank line!
Expand Down Expand Up @@ -129,6 +156,37 @@ pub fn main(has_color: bool, has_header: bool) -> i32 {
}
}

fn notify_repl_panic(target: Target, e: Box<dyn Any + Send>) -> ReplAction<'static> {
let message = if let Some(s) = e.downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = e.downcast_ref::<String>() {
s.clone()
} else {
"Unknown error".to_string()
};

let backtrace = BACKTRACE
.get()
.and_then(|storage| storage.lock().ok().as_deref_mut().and_then(Option::take))
.unwrap_or_else(|| "<Backtrace not found>".to_string());

println!(
"\
The Roc compiler had an internal error.
Please file a bug report at
https://github.com/roc-lang/roc/issues/new
Please include the following data:
Error message: {}
Stack backtrace:
{}
Machine Target: {:#?}
",
message, backtrace, target
);
ReplAction::Nothing
}

pub fn evaluate(
opt_mono: Option<MonomorphizedModule<'_>>,
problems: Problems,
Expand Down

0 comments on commit e18b437

Please sign in to comment.