Packages
kreuzberg
4.7.2
4.10.3
4.10.2
4.10.1
4.10.0
4.9.9
4.9.7
4.9.5
4.9.4
4.9.3
4.9.2
4.9.1
4.8.6
4.8.5
4.8.4
4.8.3
4.8.2
4.8.1
4.8.0
4.7.4
4.7.3
4.7.2
4.7.1
4.7.0
4.6.3
4.6.2
4.6.1
4.6.0
4.5.4
4.5.3
4.5.2
4.5.1
4.4.6
4.4.5
4.4.4
4.4.3
4.4.2
4.4.1
4.4.0
4.3.8
4.3.7
4.3.6
4.3.5
4.3.4
4.3.3
4.3.2
4.3.0
4.2.15
4.2.14
4.2.13
4.2.12
4.2.11
4.2.10
4.2.9
4.2.8
4.2.7
4.2.6
4.2.5
4.2.4
4.2.3
4.2.2
4.2.1
4.2.0
4.1.2
4.1.1
4.1.0
4.0.8
4.0.7
4.0.6
4.0.4
4.0.3
4.0.2
4.0.1
4.0.0
4.0.0-rc.27
4.0.0-rc.26
High-performance document intelligence library with OCR support
Current section
Files
Jump to
Current section
Files
native/kreuzberg_rustler/src/safe.rs
//! Safety wrapper for NIF operations.
//!
//! Wraps extraction calls with `catch_unwind` to prevent panics in native C
//! libraries (pdfium, tesseract) from crashing the BEAM VM. Instead, panics
//! are caught and returned as `{:error, reason}` tuples.
use std::panic::{self, AssertUnwindSafe};
/// Run a closure that may panic (e.g., from native C FFI) and convert panics
/// to a string error message. Logs the panic at error level with a backtrace.
///
/// Returns `Ok(T)` on success, `Err(String)` if the closure panicked.
pub fn catch_native_panic<F, T>(operation: &str, f: F) -> Result<T, String>
where
F: FnOnce() -> T,
{
match panic::catch_unwind(AssertUnwindSafe(f)) {
Ok(result) => Ok(result),
Err(payload) => {
let panic_msg = if let Some(s) = payload.downcast_ref::<&str>() {
(*s).to_string()
} else if let Some(s) = payload.downcast_ref::<String>() {
s.clone()
} else {
"unknown panic payload".to_string()
};
let backtrace = std::backtrace::Backtrace::force_capture();
tracing::error!(
operation = operation,
panic_message = %panic_msg,
backtrace = %backtrace,
"Native library panic caught in Elixir NIF — returning error instead of crashing BEAM"
);
Err(format!("Native library panic during {}: {}", operation, panic_msg))
}
}
}