From 35a60c08b9494db9c424cbfd7d989b79dc19ae7c Mon Sep 17 00:00:00 2001 From: Folke Behrens Date: Mon, 3 Apr 2023 23:33:54 +0200 Subject: [PATCH] Prevent the name_to_mib from panicking --- microchassis/src/profiling/mallctl.rs | 105 +++++++++++++++++--------- 1 file changed, 69 insertions(+), 36 deletions(-) diff --git a/microchassis/src/profiling/mallctl.rs b/microchassis/src/profiling/mallctl.rs index e78d67d..f871d31 100644 --- a/microchassis/src/profiling/mallctl.rs +++ b/microchassis/src/profiling/mallctl.rs @@ -64,65 +64,93 @@ pub fn enabled() -> Result { unsafe { raw::read_mib(&*MIB_OPT_PROF).map_err(Into::into) } } +// TODO: consider a guard pattern instead of checking for each command. +fn if_enabled(f: F) -> Result +where + F: FnOnce() -> Result, +{ + if enabled()? { + f() + } else { + Err(Error::ProfilingDisabled) + } +} + /// Writes `prof.active`. #[inline] pub fn set_active(value: bool) -> Result<(), Error> { - // SAFETY: use correct type (bool) for this mallctl command. - unsafe { raw::write_mib(&*MIB_PROF_ACTIVE, value).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct type (bool) for this mallctl command. + unsafe { raw::write_mib(&*MIB_PROF_ACTIVE, value).map_err(Into::into) } + }) } /// Reads `prof.active`. #[inline] pub fn active() -> Result { - // SAFETY: use correct type (bool) for this mallctl command. - unsafe { raw::read_mib(&*MIB_PROF_ACTIVE).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct type (bool) for this mallctl command. + unsafe { raw::read_mib(&*MIB_PROF_ACTIVE).map_err(Into::into) } + }) } /// Writes `prof.thread_active_init`. #[inline] pub fn set_thread_active_init(value: bool) -> Result<(), Error> { - // SAFETY: use correct param type (bool) for this mallctl command. - unsafe { raw::write_mib(&*MIB_PROF_THREAD_ACTIVE_INIT, value).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct param type (bool) for this mallctl command. + unsafe { raw::write_mib(&*MIB_PROF_THREAD_ACTIVE_INIT, value).map_err(Into::into) } + }) } /// Reads `prof.thread_active_init`. #[inline] pub fn thread_active_init() -> Result { - // SAFETY: use correct return type (bool) for this mallctl command. - unsafe { raw::read_mib(&*MIB_PROF_THREAD_ACTIVE_INIT).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct return type (bool) for this mallctl command. + unsafe { raw::read_mib(&*MIB_PROF_THREAD_ACTIVE_INIT).map_err(Into::into) } + }) } /// Writes `thread.prof.active`. #[inline] pub fn set_thread_active(value: bool) -> Result<(), Error> { - // SAFETY: use correct param type (bool) for this mallctl command. - unsafe { raw::write_mib(&*MIB_THREAD_PROF_ACTIVE, value).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct param type (bool) for this mallctl command. + unsafe { raw::write_mib(&*MIB_THREAD_PROF_ACTIVE, value).map_err(Into::into) } + }) } /// Reads `thread.prof.active`. #[inline] pub fn thread_active() -> Result { - // SAFETY: use correct return type (bool) for this mallctl command. - unsafe { raw::read_mib(&*MIB_THREAD_PROF_ACTIVE).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct return type (bool) for this mallctl command. + unsafe { raw::read_mib(&*MIB_THREAD_PROF_ACTIVE).map_err(Into::into) } + }) } /// Writes `prof.reset`. Optionally settings a new sample interval. #[allow(clippy::option_if_let_else, clippy::borrow_as_ptr)] #[inline] pub fn reset(sample: Option) -> Result<(), Error> { - let value = match sample { - Some(mut sample) => &mut sample as *mut _, - None => ptr::null_mut(), - }; - // SAFETY: use correct param type (*size_t) for this mallctl command. - unsafe { write_mib_ptr(&*MIB_PROF_RESET, value).map_err(Into::into) } + if_enabled(move || { + let value = match sample { + Some(mut sample) => &mut sample as *mut _, + None => ptr::null_mut(), + }; + // SAFETY: use correct param type (*size_t) for this mallctl command. + unsafe { write_mib_ptr(&*MIB_PROF_RESET, value).map_err(Into::into) } + }) } /// Reads `prof.lg_sample`. #[inline] pub fn sample_interval() -> Result { - // SAFETY: use correct return type (size_t) for this mallctl command. - unsafe { raw::read_mib(&*MIB_PROF_LG_SAMPLE).map_err(Into::into) } + if_enabled(move || { + // SAFETY: use correct return type (size_t) for this mallctl command. + unsafe { raw::read_mib(&*MIB_PROF_LG_SAMPLE).map_err(Into::into) } + }) } /// Writes `prof.dump` causing a profile dump into a file. @@ -130,25 +158,27 @@ pub fn sample_interval() -> Result { /// If not, jemalloc dumps the profile to a file based on name pattern. #[inline] pub fn dump(path: Option<&str>) -> Result>, Error> { - let ptr = match path { - Some(s) => ffi::CString::new(s)?.into_bytes_with_nul().as_ptr(), - None => ptr::null(), - }; + if_enabled(move || { + let ptr = match path { + Some(s) => ffi::CString::new(s)?.into_bytes_with_nul().as_ptr(), + None => ptr::null(), + }; - // SAFETY: use correct param type (*char+\0) for this mallctl command. - unsafe { - raw::write_mib(&*MIB_PROF_DUMP, ptr)?; - } + // SAFETY: use correct param type (*char+\0) for this mallctl command. + unsafe { + raw::write_mib(&*MIB_PROF_DUMP, ptr)?; + } - match path { - Some(path) => { - let mut f = fs::File::open(path)?; - let mut buf = Vec::new(); - io::copy(&mut f, &mut buf)?; - Ok(Some(buf)) + match path { + Some(path) => { + let mut f = fs::File::open(path)?; + let mut buf = Vec::new(); + io::copy(&mut f, &mut buf)?; + Ok(Some(buf)) + } + None => Ok(None), } - None => Ok(None), - } + }) } pub fn stats() -> Result, Error> { @@ -176,6 +206,9 @@ unsafe fn write_mib_ptr(mib: &[usize], value: *mut T) -> Result<(), Error> { #[derive(thiserror::Error, fmt::Debug)] pub enum Error { + #[error("mallctl: profiling disabled")] + ProfilingDisabled, + #[error("mallctl error: {0}")] Mallctl(#[from] MallctlError),