From ad9897b876600c45c2e1f029c230a2a495d00a28 Mon Sep 17 00:00:00 2001 From: Wenyu Zhao Date: Thu, 23 May 2024 15:40:20 +1000 Subject: [PATCH] Refactor --- mallockit/macros/src/lib.rs | 48 ++-- mallockit/src/util/malloc/malloc_api.rs | 187 +++++++--------- mallockit/src/util/malloc/rust_alloc.rs | 285 +++++++++++++----------- mallockit/src/util/sys/hooks.rs | 5 +- 4 files changed, 273 insertions(+), 252 deletions(-) diff --git a/mallockit/macros/src/lib.rs b/mallockit/macros/src/lib.rs index 16b226e..9c932a3 100644 --- a/mallockit/macros/src/lib.rs +++ b/mallockit/macros/src/lib.rs @@ -9,24 +9,42 @@ pub fn plan(_attr: TokenStream, item: TokenStream) -> TokenStream { #input mod __mallockit_plan { - pub(super) static PLAN: ::mallockit::util::Lazy = ::mallockit::util::Lazy::new(|| ::new()); + type Plan = super::#name; - ::mallockit::export_malloc_api!(PLAN, super::super::#name); - } + pub(super) static PLAN: ::mallockit::util::Lazy = ::mallockit::util::Lazy::new(|| ::new()); - ::mallockit::export_rust_global_alloc_api!(PLAN, #name); + #[cfg(any(feature = "malloc", feature = "mallockit/malloc"))] + #[::mallockit::ctor] + unsafe fn ctor() { + ::mallockit::util::sys::hooks::process_start(&*PLAN); + } + + #[cfg(target_os = "macos")] + #[no_mangle] + pub extern "C" fn mallockit_initialize_macos_tls() -> *mut u8 { + ::Mutator::current() as *mut ::mallockit::Mutator as _ + } - impl ::mallockit::plan::Singleton for #name { - fn singleton() -> &'static Self { - unsafe { &__mallockit_plan::PLAN } + impl ::mallockit::plan::Singleton for super::#name { + fn singleton() -> &'static Self { + unsafe { &PLAN } + } } + + ::mallockit::export_malloc_api!(PLAN, super::super::#name); + ::mallockit::export_rust_global_alloc_api!(super::super::#name); } - include!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/../target/generated_tests.rs" - )); - ::mallockit::rust_allocator_tests!(Global); + pub use __mallockit_plan::__mallockit_rust_api::Global; + + #[cfg(test)] + mod tests { + include!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/../target/generated_tests.rs" + )); + ::mallockit::rust_allocator_tests!(crate::Global); + } }; result.into() } @@ -42,12 +60,12 @@ pub fn mutator(_attr: TokenStream, item: TokenStream) -> TokenStream { #[cfg(not(target_os = "macos"))] mod __mallockit_mutator { #[thread_local] - pub(super) static mut MUTATOR: mallockit::util::Lazy = mallockit::util::Lazy::new(|| ::new()); + pub(super) static mut MUTATOR: ::mallockit::util::Lazy = ::mallockit::util::Lazy::new(|| ::new()); } - impl mallockit::mutator::TLS for #name { + impl ::mallockit::mutator::TLS for #name { fn new() -> Self { - ::new() + ::new() } #[cfg(not(target_os = "macos"))] diff --git a/mallockit/src/util/malloc/malloc_api.rs b/mallockit/src/util/malloc/malloc_api.rs index 688e72a..054936e 100644 --- a/mallockit/src/util/malloc/malloc_api.rs +++ b/mallockit/src/util/malloc/malloc_api.rs @@ -224,128 +224,109 @@ impl MallocAPI

{ #[doc(hidden)] macro_rules! export_malloc_api { ($plan: expr, $plan_ty: ty) => { - pub mod __mallockit { + #[cfg(any(feature = "malloc", feature = "mallockit/malloc"))] + pub mod __mallockit_malloc_api { use super::*; use $crate::Plan; - type ConcretePlan = $plan_ty; - type Malloc = $crate::util::malloc::MallocAPI; - static MALLOC_IMPL: Malloc = - $crate::util::malloc::MallocAPI::::new(&$plan); - - #[cfg(any(feature = "malloc", feature = "mallockit/malloc"))] - #[$crate::ctor] - unsafe fn ctor() { - $crate::util::sys::hooks::process_start(&*$plan); - $crate::libc::atexit($crate::util::sys::hooks::process_exit); + type Malloc = $crate::util::malloc::MallocAPI<$plan_ty>; + static MALLOC_IMPL: Malloc = $crate::util::malloc::MallocAPI::<$plan_ty>::new(&$plan); + + #[$crate::interpose] + pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 { + MALLOC_IMPL.alloc_or_enomem(size, Malloc::MIN_ALIGNMENT) } #[cfg(target_os = "macos")] - #[no_mangle] - pub extern "C" fn mallockit_initialize_macos_tls() -> *mut u8 { - MALLOC_IMPL.mutator() as *mut _ as _ + #[$crate::interpose] + pub unsafe extern "C" fn malloc_size(ptr: *mut u8) -> usize { + MALLOC_IMPL.malloc_size(ptr.into()) } - #[cfg(any(feature = "malloc", feature = "mallockit/malloc"))] - pub mod __malloc_api { - use super::{Malloc, MALLOC_IMPL}; - - #[$crate::interpose] - pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 { - MALLOC_IMPL.alloc_or_enomem(size, Malloc::MIN_ALIGNMENT) - } - - #[cfg(target_os = "macos")] - #[$crate::interpose] - pub unsafe extern "C" fn malloc_size(ptr: *mut u8) -> usize { - MALLOC_IMPL.malloc_size(ptr.into()) - } - - // #[cfg(target_os = "macos")] - // #[$crate::interpose] - // pub unsafe fn malloc_good_size(ptr: *mut u8) -> usize { - // MALLOC_IMPL.malloc_size(ptr.into()) - // } + // #[cfg(target_os = "macos")] + // #[$crate::interpose] + // pub unsafe fn malloc_good_size(ptr: *mut u8) -> usize { + // MALLOC_IMPL.malloc_size(ptr.into()) + // } - #[cfg(target_os = "linux")] - #[$crate::interpose] - pub unsafe extern "C" fn malloc_usable_size(ptr: *mut u8) -> usize { - MALLOC_IMPL.malloc_size(ptr.into()) - } + #[cfg(target_os = "linux")] + #[$crate::interpose] + pub unsafe extern "C" fn malloc_usable_size(ptr: *mut u8) -> usize { + MALLOC_IMPL.malloc_size(ptr.into()) + } - #[$crate::interpose] - pub unsafe extern "C" fn free(ptr: *mut u8) { - MALLOC_IMPL.free(ptr) - } + #[$crate::interpose] + pub unsafe extern "C" fn free(ptr: *mut u8) { + MALLOC_IMPL.free(ptr) + } - #[cfg(target_os = "linux")] - #[$crate::interpose] - pub unsafe extern "C" fn cfree(ptr: *mut u8) { - MALLOC_IMPL.free(ptr) - } + #[cfg(target_os = "linux")] + #[$crate::interpose] + pub unsafe extern "C" fn cfree(ptr: *mut u8) { + MALLOC_IMPL.free(ptr) + } - #[$crate::interpose] - pub unsafe extern "C" fn calloc(count: usize, size: usize) -> *mut u8 { - let size = count * size; - let ptr = MALLOC_IMPL.alloc_or_enomem(size, Malloc::MIN_ALIGNMENT); - std::ptr::write_bytes(ptr, 0, size); - ptr - } + #[$crate::interpose] + pub unsafe extern "C" fn calloc(count: usize, size: usize) -> *mut u8 { + let size = count * size; + let ptr = MALLOC_IMPL.alloc_or_enomem(size, Malloc::MIN_ALIGNMENT); + std::ptr::write_bytes(ptr, 0, size); + ptr + } - #[cfg(any(target_os = "linux", target_os = "macos"))] - #[$crate::interpose] - pub unsafe extern "C" fn valloc(size: usize) -> *mut u8 { - MALLOC_IMPL.alloc_or_enomem(size, Malloc::PAGE_SIZE) - } + #[cfg(any(target_os = "linux", target_os = "macos"))] + #[$crate::interpose] + pub unsafe extern "C" fn valloc(size: usize) -> *mut u8 { + MALLOC_IMPL.alloc_or_enomem(size, Malloc::PAGE_SIZE) + } - #[cfg(target_os = "linux")] - #[$crate::interpose] - pub unsafe extern "C" fn pvalloc(size: usize) -> *mut u8 { - MALLOC_IMPL.alloc_or_enomem(size, Malloc::PAGE_SIZE) - } + #[cfg(target_os = "linux")] + #[$crate::interpose] + pub unsafe extern "C" fn pvalloc(size: usize) -> *mut u8 { + MALLOC_IMPL.alloc_or_enomem(size, Malloc::PAGE_SIZE) + } - #[$crate::interpose] - pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 { - MALLOC_IMPL.reallocate_or_enomem( - ptr, - size, - cfg!(any(target_os = "linux", target_os = "windows")), - false, - ) - } + #[$crate::interpose] + pub unsafe extern "C" fn realloc(ptr: *mut u8, size: usize) -> *mut u8 { + MALLOC_IMPL.reallocate_or_enomem( + ptr, + size, + cfg!(any(target_os = "linux", target_os = "windows")), + false, + ) + } - #[cfg(target_os = "macos")] - #[$crate::interpose] - pub unsafe extern "C" fn reallocf(ptr: *mut u8, size: usize) -> *mut u8 { - MALLOC_IMPL.reallocate_or_enomem(ptr, size, false, true) - } + #[cfg(target_os = "macos")] + #[$crate::interpose] + pub unsafe extern "C" fn reallocf(ptr: *mut u8, size: usize) -> *mut u8 { + MALLOC_IMPL.reallocate_or_enomem(ptr, size, false, true) + } - #[cfg(any(target_os = "linux", target_os = "macos"))] - #[$crate::interpose] - pub unsafe extern "C" fn posix_memalign( - ptr: *mut *mut u8, - alignment: usize, - size: usize, - ) -> i32 { - MALLOC_IMPL.posix_memalign(ptr, alignment, size) - } + #[cfg(any(target_os = "linux", target_os = "macos"))] + #[$crate::interpose] + pub unsafe extern "C" fn posix_memalign( + ptr: *mut *mut u8, + alignment: usize, + size: usize, + ) -> i32 { + MALLOC_IMPL.posix_memalign(ptr, alignment, size) + } - #[cfg(target_os = "linux")] - #[$crate::interpose] - pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut u8 { - MALLOC_IMPL.memalign(alignment, size) - } + #[cfg(target_os = "linux")] + #[$crate::interpose] + pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut u8 { + MALLOC_IMPL.memalign(alignment, size) + } - #[cfg(target_os = "linux")] - #[$crate::interpose] - pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut u8 { - MALLOC_IMPL.aligned_alloc(size, alignment, true, false) - } + #[cfg(target_os = "linux")] + #[$crate::interpose] + pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut u8 { + MALLOC_IMPL.aligned_alloc(size, alignment, true, false) + } - #[cfg(target_os = "windows")] - #[$crate::interpose] - pub unsafe extern "C" fn _aligned_malloc(size: usize, alignment: usize) -> *mut u8 { - MALLOC_IMPL.aligned_alloc(size, alignment, false, true) - } + #[cfg(target_os = "windows")] + #[$crate::interpose] + pub unsafe extern "C" fn _aligned_malloc(size: usize, alignment: usize) -> *mut u8 { + MALLOC_IMPL.aligned_alloc(size, alignment, false, true) } } }; diff --git a/mallockit/src/util/malloc/rust_alloc.rs b/mallockit/src/util/malloc/rust_alloc.rs index a5141da..994e206 100644 --- a/mallockit/src/util/malloc/rust_alloc.rs +++ b/mallockit/src/util/malloc/rust_alloc.rs @@ -1,156 +1,175 @@ #[macro_export] #[doc(hidden)] macro_rules! export_rust_global_alloc_api { - ($plan: expr, $plan_ty: ty) => { - pub struct Global; + ($plan_ty: ty) => { + pub mod __mallockit_rust_api { + use $crate::util::{Layout, LayoutUtils}; + use $crate::{Mutator, Plan}; - impl Global { - pub fn __fix_layout(mut layout: ::std::alloc::Layout) -> Layout { - if layout.align() < $crate::util::constants::MIN_ALIGNMENT { - layout = layout - .align_to($crate::util::constants::MIN_ALIGNMENT) - .unwrap(); + pub struct Global; + + impl Global { + fn __fix_layout(mut layout: ::std::alloc::Layout) -> Layout { + if layout.align() < $crate::util::constants::MIN_ALIGNMENT { + layout = layout + .align_to($crate::util::constants::MIN_ALIGNMENT) + .unwrap(); + } + layout = unsafe { layout.pad_to_align_unchecked() }; + layout } - layout = unsafe { layout.pad_to_align_unchecked() }; - layout } - } - unsafe impl ::std::alloc::Allocator for Global { - fn allocate( - &self, - mut layout: ::std::alloc::Layout, - ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> { - layout = Self::__fix_layout(layout); - let start = <$plan_ty as $crate::Plan>::Mutator::current() - .alloc(layout) - .unwrap_or($crate::util::Address::ZERO); - let slice = unsafe { - ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, layout.size()) - }; - ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) - } + unsafe impl ::std::alloc::Allocator for Global { + fn allocate( + &self, + mut layout: ::std::alloc::Layout, + ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> + { + layout = Self::__fix_layout(layout); + let start = <$plan_ty as $crate::Plan>::Mutator::current() + .alloc(layout) + .unwrap_or($crate::util::Address::ZERO); + let slice = unsafe { + ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, layout.size()) + }; + ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) + } - fn allocate_zeroed( - &self, - mut layout: ::std::alloc::Layout, - ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> { - layout = Self::__fix_layout(layout); - let start = <$plan_ty as $crate::Plan>::Mutator::current() - .alloc_zeroed(layout) - .unwrap_or($crate::util::Address::ZERO); - let slice = unsafe { - ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, layout.size()) - }; - ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) - } + fn allocate_zeroed( + &self, + mut layout: ::std::alloc::Layout, + ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> + { + layout = Self::__fix_layout(layout); + let start = <$plan_ty as $crate::Plan>::Mutator::current() + .alloc_zeroed(layout) + .unwrap_or($crate::util::Address::ZERO); + let slice = unsafe { + ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, layout.size()) + }; + ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) + } - unsafe fn deallocate( - &self, - ptr: ::std::ptr::NonNull, - layout: ::std::alloc::Layout, - ) { - <$plan_ty as $crate::Plan>::Mutator::current().dealloc(ptr.as_ptr().into()) - } + unsafe fn deallocate( + &self, + ptr: ::std::ptr::NonNull, + layout: ::std::alloc::Layout, + ) { + <$plan_ty as $crate::Plan>::Mutator::current().dealloc(ptr.as_ptr().into()) + } - unsafe fn grow( - &self, - ptr: ::std::ptr::NonNull, - old_layout: ::std::alloc::Layout, - mut new_layout: ::std::alloc::Layout, - ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> { - debug_assert!( - new_layout.size() >= old_layout.size(), - "`new_layout.size()` must be greater than or equal to `old_layout.size()`" - ); + unsafe fn grow( + &self, + ptr: ::std::ptr::NonNull, + old_layout: ::std::alloc::Layout, + mut new_layout: ::std::alloc::Layout, + ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> + { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); - new_layout = Self::__fix_layout(new_layout); - let start = <$plan_ty as $crate::Plan>::Mutator::current() - .realloc(ptr.as_ptr().into(), new_layout) - .unwrap_or($crate::util::Address::ZERO); - let slice = unsafe { - ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, new_layout.size()) - }; - ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) - } + new_layout = Self::__fix_layout(new_layout); + let start = <$plan_ty as $crate::Plan>::Mutator::current() + .realloc(ptr.as_ptr().into(), new_layout) + .unwrap_or($crate::util::Address::ZERO); + let slice = unsafe { + ::std::slice::from_raw_parts_mut( + start.as_mut() as *mut u8, + new_layout.size(), + ) + }; + ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) + } - unsafe fn grow_zeroed( - &self, - ptr: ::std::ptr::NonNull, - old_layout: ::std::alloc::Layout, - mut new_layout: ::std::alloc::Layout, - ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> { - debug_assert!( - new_layout.size() >= old_layout.size(), - "`new_layout.size()` must be greater than or equal to `old_layout.size()`" - ); + unsafe fn grow_zeroed( + &self, + ptr: ::std::ptr::NonNull, + old_layout: ::std::alloc::Layout, + mut new_layout: ::std::alloc::Layout, + ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> + { + debug_assert!( + new_layout.size() >= old_layout.size(), + "`new_layout.size()` must be greater than or equal to `old_layout.size()`" + ); - new_layout = Self::__fix_layout(new_layout); - let start = <$plan_ty as $crate::Plan>::Mutator::current() - .realloc_zeroed(ptr.as_ptr().into(), new_layout) - .unwrap_or($crate::util::Address::ZERO); - let slice = unsafe { - ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, new_layout.size()) - }; - ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) - } + new_layout = Self::__fix_layout(new_layout); + let start = <$plan_ty as $crate::Plan>::Mutator::current() + .realloc_zeroed(ptr.as_ptr().into(), new_layout) + .unwrap_or($crate::util::Address::ZERO); + let slice = unsafe { + ::std::slice::from_raw_parts_mut( + start.as_mut() as *mut u8, + new_layout.size(), + ) + }; + ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) + } - unsafe fn shrink( - &self, - ptr: ::std::ptr::NonNull, - old_layout: ::std::alloc::Layout, - mut new_layout: ::std::alloc::Layout, - ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> { - debug_assert!( - new_layout.size() <= old_layout.size(), - "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" - ); + unsafe fn shrink( + &self, + ptr: ::std::ptr::NonNull, + old_layout: ::std::alloc::Layout, + mut new_layout: ::std::alloc::Layout, + ) -> ::std::result::Result<::std::ptr::NonNull<[u8]>, ::std::alloc::AllocError> + { + debug_assert!( + new_layout.size() <= old_layout.size(), + "`new_layout.size()` must be smaller than or equal to `old_layout.size()`" + ); - new_layout = Self::__fix_layout(new_layout); - let start = <$plan_ty as $crate::Plan>::Mutator::current() - .realloc(ptr.as_ptr().into(), new_layout) - .unwrap_or($crate::util::Address::ZERO); - let slice = unsafe { - ::std::slice::from_raw_parts_mut(start.as_mut() as *mut u8, new_layout.size()) - }; - ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) + new_layout = Self::__fix_layout(new_layout); + let start = <$plan_ty as $crate::Plan>::Mutator::current() + .realloc(ptr.as_ptr().into(), new_layout) + .unwrap_or($crate::util::Address::ZERO); + let slice = unsafe { + ::std::slice::from_raw_parts_mut( + start.as_mut() as *mut u8, + new_layout.size(), + ) + }; + ::std::result::Result::Ok(::std::ptr::NonNull::from(slice)) + } } - } - unsafe impl ::std::alloc::GlobalAlloc for Global { - unsafe fn alloc(&self, mut layout: ::std::alloc::Layout) -> *mut u8 { - layout = Self::__fix_layout(layout); - <$plan_ty as $crate::Plan>::Mutator::current() - .alloc(layout) - .unwrap_or($crate::util::Address::ZERO) - .into() - } + unsafe impl ::std::alloc::GlobalAlloc for Global { + unsafe fn alloc(&self, mut layout: ::std::alloc::Layout) -> *mut u8 { + layout = Self::__fix_layout(layout); + <$plan_ty as $crate::Plan>::Mutator::current() + .alloc(layout) + .unwrap_or($crate::util::Address::ZERO) + .into() + } - unsafe fn alloc_zeroed(&self, mut layout: ::std::alloc::Layout) -> *mut u8 { - layout = Self::__fix_layout(layout); - <$plan_ty as $crate::Plan>::Mutator::current() - .alloc_zeroed(layout) - .unwrap_or($crate::util::Address::ZERO) - .into() - } + unsafe fn alloc_zeroed(&self, mut layout: ::std::alloc::Layout) -> *mut u8 { + layout = Self::__fix_layout(layout); + <$plan_ty as $crate::Plan>::Mutator::current() + .alloc_zeroed(layout) + .unwrap_or($crate::util::Address::ZERO) + .into() + } - unsafe fn dealloc(&self, ptr: *mut u8, _layout: ::std::alloc::Layout) { - <$plan_ty as $crate::Plan>::Mutator::current().dealloc(ptr.into()) - } + unsafe fn dealloc(&self, ptr: *mut u8, _layout: ::std::alloc::Layout) { + <$plan_ty as $crate::Plan>::Mutator::current().dealloc(ptr.into()) + } - unsafe fn realloc( - &self, - ptr: *mut u8, - layout: ::std::alloc::Layout, - new_size: usize, - ) -> *mut u8 { - let mut new_layout = - unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; - new_layout = Self::__fix_layout(new_layout); - <$plan_ty as $crate::Plan>::Mutator::current() - .realloc(ptr.into(), new_layout) - .unwrap_or($crate::util::Address::ZERO) - .into() + unsafe fn realloc( + &self, + ptr: *mut u8, + layout: ::std::alloc::Layout, + new_size: usize, + ) -> *mut u8 { + let mut new_layout = + unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) }; + new_layout = Self::__fix_layout(new_layout); + <$plan_ty as $crate::Plan>::Mutator::current() + .realloc(ptr.into(), new_layout) + .unwrap_or($crate::util::Address::ZERO) + .into() + } } } }; diff --git a/mallockit/src/util/sys/hooks.rs b/mallockit/src/util/sys/hooks.rs index 87882d4..30323c7 100644 --- a/mallockit/src/util/sys/hooks.rs +++ b/mallockit/src/util/sys/hooks.rs @@ -13,11 +13,14 @@ pub fn set_panic_handler() { pub extern "C" fn process_start(plan: &'static impl Plan) { set_panic_handler(); + unsafe { + libc::atexit(process_exit); + } #[cfg(target_os = "macos")] crate::util::malloc::macos_malloc_zone::init(); plan.init(); } -pub extern "C" fn process_exit() { +extern "C" fn process_exit() { crate::stat::report(); }