Skip to content

Commit

Permalink
Added trace to module crash report (#192)
Browse files Browse the repository at this point in the history
* Added trace to module crash report

The trace provided by Redis is not fully compatible to rust.
The PR adds a section to the crash report (under the module
info section) with the rust trace.

* review fixes
  • Loading branch information
MeirShpilraien authored Oct 28, 2021
1 parent 9bd08b6 commit 451db14
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ enum-primitive-derive = "^0.1"
num-traits = "^0.2"
strum_macros = "0.22"
#failure = "0.1"
backtrace = "0.3"

[dev-dependencies]
anyhow = "1.0.38"
Expand Down
15 changes: 14 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ pub use crate::context::thread_safe::{DetachedFromClient, ThreadSafeContext};
pub use crate::raw::NotifyEvent;

pub use crate::context::Context;
pub use crate::raw::Status;
pub use crate::raw::*;
pub use crate::redismodule::*;
use backtrace::Backtrace;

/// Ideally this would be `#[cfg(not(test))]`, but that doesn't work:
/// https://github.com/rust-lang/rust/issues/59168#issuecomment-472653680
Expand Down Expand Up @@ -59,3 +60,15 @@ fn from_byte_string(byte_str: *const c_char, length: size_t) -> Result<String, U

String::from_utf8(vec_str).map_err(|e| e.utf8_error())
}

pub fn base_info_func(ctx: *mut RedisModuleInfoCtx, for_crash_report: bool) {
if !for_crash_report {
return;
}
// add rust trace into the crash report
if add_info_section(ctx, Some("trace")) == Status::Ok {
let current_backtrace = Backtrace::new();
let trace = format!("{:?}", current_backtrace);
raw::add_info_field_str(ctx, "trace", &trace);
}
}
9 changes: 9 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ macro_rules! redis_module {
]),* $(,)*
])?
) => {
extern "C" fn __info_func(
ctx: *mut $crate::raw::RedisModuleInfoCtx,
for_crash_report: i32,
) {
$crate::base_info_func(ctx, for_crash_report == 1);
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn RedisModule_OnLoad(
Expand Down Expand Up @@ -168,6 +175,8 @@ macro_rules! redis_module {
)*
)?

raw::register_info_function(ctx, Some(__info_func));

raw::Status::Ok as c_int
}

Expand Down
34 changes: 34 additions & 0 deletions src/raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,40 @@ pub fn subscribe_to_server_event(
unsafe { RedisModule_SubscribeToServerEvent.unwrap()(ctx, event, callback).into() }
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn register_info_function(
ctx: *mut RedisModuleCtx,
callback: RedisModuleInfoFunc,
) -> Status {
unsafe { RedisModule_RegisterInfoFunc.unwrap()(ctx, callback).into() }
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn add_info_section(
ctx: *mut RedisModuleInfoCtx,
name: Option<&str>, // assume NULL terminated
) -> Status {
let name = name.map(|n| {
CString::new(n).unwrap()
});
if let Some(n) = name {
unsafe { RedisModule_InfoAddSection.unwrap()(ctx, n.as_ptr() as *mut c_char).into() }
} else {
unsafe { RedisModule_InfoAddSection.unwrap()(ctx, ptr::null_mut()).into() }
}
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
pub fn add_info_field_str(
ctx: *mut RedisModuleInfoCtx,
name: &str, // assume NULL terminated
content: &str,
) -> Status {
let name = CString::new(name).unwrap();
let content = RedisString::create(ptr::null_mut(), content);
unsafe { RedisModule_InfoAddFieldString.unwrap()(ctx, name.as_ptr() as *mut c_char, content.inner).into() }
}

#[cfg(feature = "experimental-api")]
pub fn export_shared_api(
ctx: *mut RedisModuleCtx,
Expand Down

0 comments on commit 451db14

Please sign in to comment.