62 lines
1.7 KiB
Rust
62 lines
1.7 KiB
Rust
// SPDX-FileCopyrightText: 2023 Foundation Devices Inc.
|
|
// SPDX-FileCopyrightText: 2024 Foundation Devices Inc.
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
use log::{error, warn};
|
|
use std::cell::RefCell;
|
|
use std::error::Error;
|
|
use std::ffi::{c_char, CString};
|
|
//pub(crate) use crate::unwrap_or_return;
|
|
|
|
thread_local! {
|
|
static LAST_ERROR: RefCell<Option<Box<dyn Error>>> = RefCell::new(None);
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub unsafe extern "C" fn tor_last_error_message() -> *const c_char {
|
|
let last_error = match crate::error::take_last_error() {
|
|
Some(err) => err,
|
|
None => return CString::new("").unwrap().into_raw(),
|
|
};
|
|
|
|
let error_message = last_error.to_string();
|
|
CString::new(error_message).unwrap().into_raw()
|
|
}
|
|
|
|
macro_rules! unwrap_or_return {
|
|
($a:expr,$b:expr) => {
|
|
match $a {
|
|
Ok(x) => x,
|
|
Err(e) => {
|
|
update_last_error(e);
|
|
return $b;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
/// Update the most recent error, clearing whatever may have been there before.
|
|
pub fn update_last_error<E: Error + 'static>(err: E) {
|
|
error!("Setting LAST_ERROR: {}", err);
|
|
|
|
{
|
|
// Print a pseudo-backtrace for this error, following back each error's
|
|
// cause until we reach the root error.
|
|
let mut cause = err.source();
|
|
while let Some(parent_err) = cause {
|
|
warn!("Caused by: {}", parent_err);
|
|
cause = parent_err.source();
|
|
}
|
|
}
|
|
|
|
LAST_ERROR.with(|prev| {
|
|
*prev.borrow_mut() = Some(Box::new(err));
|
|
});
|
|
}
|
|
|
|
/// Retrieve the most recent error, clearing it in the process.
|
|
pub fn take_last_error() -> Option<Box<dyn Error>> {
|
|
LAST_ERROR.with(|prev| prev.borrow_mut().take())
|
|
}
|