diff --git a/Cargo.lock b/Cargo.lock index b3b56d9..51acc30 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -96,7 +96,6 @@ dependencies = [ "libc", "memchr", "recolored", - "stackalloc", "tracing", "tracing-error", "tracing-subscriber", @@ -325,30 +324,6 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "sharded-slab" version = "0.1.4" @@ -364,16 +339,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" -[[package]] -name = "stackalloc" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5598a6751ba6c0735dbb9d88910ffce156a0bfdbfb7548f915b52990470bc7" -dependencies = [ - "cc", - "rustc_version", -] - [[package]] name = "syn" version = "1.0.91" diff --git a/Cargo.toml b/Cargo.toml index b7253a8..b27f284 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ mode-buffered = ["jemalloc", "bytes"] # * Statically sized (the program can infer the size of standard input.) # * The standard input file/buffer pipe size is large enough to pre-allocate enough splicing space to use up the rest of your physical RAM. # (This will very likely not happen unless you're specifically trying to make it happen, however.) -memfile = ["bitflags", "lazy_static", "stackalloc"] +memfile = ["bitflags", "lazy_static"] # `memfile`: When unable to determine the size of the input, preallocate the buffer to a multiple of the system page-size before writing to it. This can save extra `ftruncate()` calls, but will also result in the buffer needing to be truncated to the correct size at the end if the sizes as not matched. # @@ -87,5 +87,4 @@ recolored = { version = "1.9.3", optional = true } memchr = "2.4.1" lazy_format = "1.10.0" bitflags = {version = "1.3.2", optional = true } -stackalloc = {version = "1.1.2", optional = true } lazy_static = { version = "1.4.0", optional = true } diff --git a/src/main.rs b/src/main.rs index d6044ff..d7e760f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,8 +5,6 @@ #[cfg(feature="memfile")] #[macro_use] extern crate lazy_static; -#[cfg(feature="memfile")] -extern crate stackalloc; /// Run this statement only if `tracing` is enabled macro_rules! if_trace { diff --git a/src/memfile.rs b/src/memfile.rs index c194eeb..b57a723 100644 --- a/src/memfile.rs +++ b/src/memfile.rs @@ -317,11 +317,15 @@ impl RawFile } /// Open a new in-memory (W+R) file with an optional name and a fixed size. - #[cfg_attr(feature="logging", instrument(err))] + #[cfg_attr(feature="logging", instrument(level="debug", skip_all, err))] pub fn open_mem(name: Option<&str>, len: usize) -> Result { + use std::{ + ffi::CString, + borrow::Cow, + }; lazy_static! { - static ref DEFAULT_NAME: String = format!(concat!("", "{}", ":", line!(), "-", column!(), ">"), function!()); //TODO: If it turns out memfd_create() requires an `&'static str`; remove the use of stackalloc, and have this variable be a nul-terminated CString instead. + static ref DEFAULT_NAME: CString = CString::new(format!(concat!("", "{}", ":", line!(), "-", column!(), ">"), function!())).unwrap(); } use libc::{ @@ -330,42 +334,39 @@ impl RawFile }; use error::MemfileCreationStep::*; - let rname = name.unwrap_or(&DEFAULT_NAME); + let bname: Cow = match name { + Some(s) => Cow::Owned(CString::new(Vec::from(s)).expect("Invalid name")), + None => Cow::Borrowed(&DEFAULT_NAME), + }; + + let bname = bname.as_bytes_with_nul(); + if_trace!(trace!("created nul-terminated buffer for name `{:?}': ({})", std::str::from_utf8(bname), bname.len())); - stackalloc::alloca_zeroed(rname.len()+1, move |bname| { //XXX: Isn't the whole point of making `name` `&'static` that I don't know if `memfd_create()` requires static-lifetime name strings? TODO: Check this - #[cfg(feature="logging")] - let _span = info_span!("stack_name_cpy", size = bname.len()); - #[cfg(feature="logging")] - let _span_lock = _span.enter(); - - macro_rules! attempt_call - { - ($errcon:literal, $expr:expr, $step:expr) => { - //if_trace!(debug!("attempting systemcall")); - match unsafe { - $expr - } { - $errcon => { - if_trace!(warn!("systemcall failed: {}", error::raw_errno())); - Err($step) - }, - x => Ok(x) - } + macro_rules! attempt_call + { + ($errcon:literal, $expr:expr, $step:expr) => { + //if_trace!(debug!("attempting systemcall")); + match unsafe { + $expr + } { + $errcon => { + if_trace!(warn!("systemcall failed: {}", error::raw_errno())); + Err($step) + }, + x => Ok(x) } } + } + + let fd = attempt_call!(-1, memfd_create(bname.as_ptr() as *const _, MEMFD_CREATE_FLAGS), Create(name.map(str::to_owned), MEMFD_CREATE_FLAGS)) + .map(Self::take_ownership_of_unchecked)?; // Ensures `fd` is dropped if any subsequent calls fail - if_trace!(trace!("copying {rname:p} `{rname}' (sz: {}) -> nul-terminated {:p}", rname.len(), bname)); - let bname = { - unsafe { - std::ptr::copy_nonoverlapping(rname.as_ptr(), bname.as_mut_ptr(), rname.len()); - } - debug_assert_eq!(bname[rname.len()], 0, "Copied name string not null-terminated?"); - bname.as_ptr() - }; - - let fd = attempt_call!(-1, memfd_create(bname as *const _, MEMFD_CREATE_FLAGS), Create(name.map(str::to_owned), MEMFD_CREATE_FLAGS)) - .map(Self::take_ownership_of_unchecked)?; // Ensures `fd` is dropped if any subsequent calls fail - + #[cfg(feature="logging")] + let using_memfile = debug_span!("setup_memfd", fd = ?fd.0.get()); + { + #[cfg(feature="logging")] + let _span = using_memfile.enter(); + if len > 0 { attempt_call!(-1 , fallocate(fd.0.get(), 0, 0, len.try_into() @@ -379,14 +380,14 @@ impl RawFile , io::Error::last_os_error()) .expect("Failed to check seek position in fd") , 0, "memfd seek position is non-zero after fallocate()"); - if_trace!(if seeked != 0 { warn!("Trace offset is non-zero: {seeked}") } else { trace!("Trace offset verified ok") }); + if_trace!(if seeked != 0 { warn!("Seek offset is non-zero: {seeked}") } else { trace!("Seek offset verified ok") }); } } else { if_trace!(trace!("No length provided, skipping fallocate() call")); } - - Ok(fd) - }) + } + Ok(fd) + } } @@ -515,9 +516,11 @@ mod tests file.seek(SeekFrom::Start(0))?; file }; - let v: Vec = stackalloc::alloca_zeroed(STRING.len(), |buf| { - file.read_exact(buf).map(|_| buf.into()) - })?; + let v = { + let mut buf = vec![0; STRING.len()]; + file.read_exact(&mut buf[..])?; + buf + }; assert_eq!(v.len(), STRING.len(), "Invalid read size."); assert_eq!(&v[..], &STRING[..], "Invalid read data.");