forked from openzfs/zfs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
use lazy_static_ptr! to store pointer to lazy_static globals for debu…
…gging (openzfs#277) We would like to be able to print the log messages from a core file. Unfortunately, lazy_static! makes it hard to get to the global object from the debugger. We would like to save the pointer in a global variable so that we can easily dereference it from rust-gdb. The way we are saving LOG_MESSAGES_PTR currently is not right; we're saving the location of the variable on the stack, which will be moved into the "real" location after it is returned. This commit solves the problem by allocating the data on the heap (inside a `Box`), so that we can know its address before the initializer returns. Because this is a little tricky, and you have to name the (potentially complicated) type of the variable 3 times, a new macro is introduced to do this for us. Now in the debugger you can do: ``` (gdb) p util::logging::LOG_MESSAGES_PTR.p.value.data $1 = core::cell::UnsafeCell<alloc::collections::vec_deque::VecDeque<alloc::string::String, alloc::alloc::Global>> {value: VecDeque(size=28) = { ... "[2022-03-04 23:01:49.089][zfs_object_agent][ERROR] Starting ZFS Object Agent (zfs-0.7.0-6003-g5b402b78c). Local timezone is +00:00 (+00:00)", ```
- Loading branch information
Showing
5 changed files
with
79 additions
and
11 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
pub use lazy_static::lazy_static; | ||
pub use paste::paste; | ||
pub use std::sync::atomic::{AtomicPtr, Ordering}; | ||
|
||
/// This macro is similar to `lazy_static!`, but for each static created, it creates an | ||
/// additional static variable with the `_PTR` suffix, which is an `AtomicPtr` to the contents of | ||
/// the lazy_static variable. This can be used by the debugger to find the contents of the | ||
/// lazy_static, which are otherwise buried inside a closure, which makes it hard to name from | ||
/// the global context of the debugger. | ||
/// | ||
/// For example: | ||
/// ``` | ||
/// lazy_static_ptr! { | ||
/// pub static ref STRINGS: Mutex<Vec<String>> = Default::default(); | ||
/// } | ||
/// ``` | ||
/// This will declare a `pub static` variable named `STRINGS` which will deref to a | ||
/// `Box<Mutex<Vec<String>>>`, similar to lazy_static!. Additionally, it will declare | ||
/// ``` | ||
/// static STRINGS_PTR: AtomicPtr<Mutex<Vec<String>>> = ...; | ||
/// ``` | ||
/// When `STRINGS` is initialized (on first dereference, or the .initialize() method), | ||
/// `STRINGS_PTR` will be set to the location of the value returned by the initializer. | ||
/// | ||
/// This macro uses `lazy_static!` internally. In order to compute the value's location in the | ||
/// lazy_static initializer, it is allocated on the heap (in a `Box`), so `STRINGS` actually | ||
/// dereferences to a `Box<Mutex<Vec<String>>>`, which itself deref's to a `Mutex<Vec<String>>`. | ||
/// So the contents can be referred to by double-dereferenceing the global, `**STRINGS`. This | ||
/// happens automatically for method calls, e.g. `STRINGS.lock()` | ||
#[macro_export] | ||
macro_rules! lazy_static_ptr { | ||
// "pub" declaration | ||
(pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { | ||
$crate::lazy_static_ptr!{ @IMPL (pub) $N: $T = $e; } | ||
$crate::lazy_static_ptr!($($t)*); | ||
}; | ||
|
||
// non-"pub" declaration | ||
(static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => { | ||
$crate::lazy_static_ptr!{ @IMPL () $N: $T = $e; } | ||
$crate::lazy_static_ptr!($($t)*); | ||
}; | ||
|
||
// internal implementation | ||
(@IMPL ($($vis:tt)*) $N:ident : $T:ty = $e:expr; $($t:tt)*) => { | ||
$crate::lazy_static_ptr::paste! { | ||
static [<$N _PTR>]: $crate::lazy_static_ptr::AtomicPtr<$T> = | ||
$crate::lazy_static_ptr::AtomicPtr::new(::std::ptr::null_mut()); | ||
} | ||
$crate::lazy_static_ptr::lazy_static! { | ||
$($vis)* static ref $N: Box<$T> = { | ||
let mut this: Box<$T> = Box::new($e); | ||
$crate::lazy_static_ptr::paste! { | ||
[<$N _PTR>].store(&mut *this, $crate::lazy_static_ptr::Ordering::Relaxed); | ||
} | ||
this | ||
}; | ||
} | ||
}; | ||
|
||
// empty trailing tokens | ||
() => () | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters