markdown_preview: Remove `recoverable_panic` and fix mermaid hex parsing panic (#50470)

Smit Barmase created

#50176 added `recoverable_panic` to swallow mermaid panics, then #50280
fixed it in upstream. This PR removes the workaround so future panics
reach Sentry. Also bumps `mermaid-rs-renderer` to fix a hex parsing
panic.

Release Notes:

- N/A

Change summary

Cargo.lock                                       |  6 +--
Cargo.toml                                       |  2 
crates/crashes/Cargo.toml                        |  1 
crates/crashes/src/crashes.rs                    | 36 -----------------
crates/markdown_preview/Cargo.toml               |  1 
crates/markdown_preview/src/markdown_renderer.rs |  4 -
6 files changed, 5 insertions(+), 45 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -4120,7 +4120,6 @@ dependencies = [
 name = "crashes"
 version = "0.1.0"
 dependencies = [
- "anyhow",
  "bincode",
  "cfg-if",
  "crash-handler",
@@ -8664,7 +8663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
 dependencies = [
  "equivalent",
- "hashbrown 0.16.1",
+ "hashbrown 0.15.5",
  "serde",
  "serde_core",
 ]
@@ -10174,7 +10173,6 @@ dependencies = [
  "anyhow",
  "async-recursion",
  "collections",
- "crashes",
  "editor",
  "fs",
  "gpui",
@@ -10400,7 +10398,7 @@ dependencies = [
 [[package]]
 name = "mermaid-rs-renderer"
 version = "0.2.0"
-source = "git+https://github.com/zed-industries/mermaid-rs-renderer?rev=9d8360d9cea10dc4bc86d7b8012cc6e9656e6cf2#9d8360d9cea10dc4bc86d7b8012cc6e9656e6cf2"
+source = "git+https://github.com/zed-industries/mermaid-rs-renderer?rev=a1f8fc03bf7293018136fb8e60d83551d2dd5732#a1f8fc03bf7293018136fb8e60d83551d2dd5732"
 dependencies = [
  "anyhow",
  "fontdb 0.16.2",

Cargo.toml 🔗

@@ -370,7 +370,7 @@ markdown_preview = { path = "crates/markdown_preview" }
 svg_preview = { path = "crates/svg_preview" }
 media = { path = "crates/media" }
 menu = { path = "crates/menu" }
-mermaid-rs-renderer = { git = "https://github.com/zed-industries/mermaid-rs-renderer", rev = "9d8360d9cea10dc4bc86d7b8012cc6e9656e6cf2", default-features = false }
+mermaid-rs-renderer = { git = "https://github.com/zed-industries/mermaid-rs-renderer", rev = "a1f8fc03bf7293018136fb8e60d83551d2dd5732", default-features = false }
 migrator = { path = "crates/migrator" }
 mistral = { path = "crates/mistral" }
 multi_buffer = { path = "crates/multi_buffer" }

crates/crashes/Cargo.toml 🔗

@@ -6,7 +6,6 @@ edition.workspace = true
 license = "GPL-3.0-or-later"
 
 [dependencies]
-anyhow.workspace = true
 bincode.workspace = true
 cfg-if.workspace = true
 crash-handler.workspace = true

crates/crashes/src/crashes.rs 🔗

@@ -4,7 +4,6 @@ use log::info;
 use minidumper::{Client, LoopAction, MinidumpBinary};
 use release_channel::{RELEASE_CHANNEL, ReleaseChannel};
 use serde::{Deserialize, Serialize};
-use std::cell::Cell;
 use std::mem;
 
 #[cfg(not(target_os = "windows"))]
@@ -16,7 +15,7 @@ use std::{
     env,
     fs::{self, File},
     io,
-    panic::{self, AssertUnwindSafe, PanicHookInfo},
+    panic::{self, PanicHookInfo},
     path::{Path, PathBuf},
     process::{self},
     sync::{
@@ -27,31 +26,6 @@ use std::{
     time::Duration,
 };
 
-thread_local! {
-    static ALLOW_UNWIND: Cell<bool> = const { Cell::new(false) };
-}
-
-/// Catch a panic as an error instead of aborting the process. Unlike plain
-/// `catch_unwind`, this bypasses the crash-reporting panic hook which would
-/// normally abort before unwinding can occur.
-///
-/// **Use sparingly.** Prefer this only for isolating third-party code
-/// that is known to panic, where you want to handle the failure gracefully
-/// instead of crashing.
-pub fn recoverable_panic<T>(closure: impl FnOnce() -> T) -> anyhow::Result<T> {
-    ALLOW_UNWIND.with(|flag| flag.set(true));
-    let result = panic::catch_unwind(AssertUnwindSafe(closure));
-    ALLOW_UNWIND.with(|flag| flag.set(false));
-    result.map_err(|payload| {
-        let message = payload
-            .downcast_ref::<&str>()
-            .map(|s| s.to_string())
-            .or_else(|| payload.downcast_ref::<String>().cloned())
-            .unwrap_or_else(|| "unknown panic".to_string());
-        anyhow::anyhow!("panic: {message}")
-    })
-}
-
 // set once the crash handler has initialized and the client has connected to it
 pub static CRASH_HANDLER: OnceLock<Arc<Client>> = OnceLock::new();
 // set when the first minidump request is made to avoid generating duplicate crash reports
@@ -83,9 +57,6 @@ pub fn init(crash_init: InitCrashHandler, spawn: impl FnOnce(BoxFuture<'static,
     if !should_install_crash_handler() {
         let old_hook = panic::take_hook();
         panic::set_hook(Box::new(move |info| {
-            if ALLOW_UNWIND.with(|flag| flag.get()) {
-                return;
-            }
             unsafe { env::set_var("RUST_BACKTRACE", "1") };
             old_hook(info);
             // prevent the macOS crash dialog from popping up
@@ -351,11 +322,6 @@ pub fn panic_hook(info: &PanicHookInfo) {
     let current_thread = std::thread::current();
     let thread_name = current_thread.name().unwrap_or("<unnamed>");
 
-    if ALLOW_UNWIND.with(|flag| flag.get()) {
-        log::error!("thread '{thread_name}' panicked at {span} (allowing unwind):\n{message}");
-        return;
-    }
-
     // wait 500ms for the crash handler process to start up
     // if it's still not there just write panic info and no minidump
     let retry_frequency = Duration::from_millis(100);

crates/markdown_preview/Cargo.toml 🔗

@@ -18,7 +18,6 @@ test-support = []
 anyhow.workspace = true
 async-recursion.workspace = true
 collections.workspace = true
-crashes.workspace = true
 editor.workspace = true
 fs.workspace = true
 gpui.workspace = true

crates/markdown_preview/src/markdown_renderer.rs 🔗

@@ -133,9 +133,7 @@ impl CachedMermaidDiagram {
         let _task = cx.spawn(async move |this, cx| {
             let value = cx
                 .background_spawn(async move {
-                    let svg_string = crashes::recoverable_panic(|| {
-                        mermaid_rs_renderer::render(&contents.contents)
-                    })??;
+                    let svg_string = mermaid_rs_renderer::render(&contents.contents)?;
                     let scale = contents.scale as f32 / 100.0;
                     svg_renderer
                         .render_single_frame(svg_string.as_bytes(), scale, true)