Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
ad16f35
fix CreateFileMapping arguments: use default pagefile instead of real…
yellowhatter Feb 13, 2025
b360fe9
fix clippy
yellowhatter Feb 13, 2025
3803baf
fix clippy
yellowhatter Feb 13, 2025
bd20b80
split new_map and open_map
yellowhatter Feb 13, 2025
471c0f9
Update windows.rs
yellowhatter Feb 13, 2025
0a43b2d
Update windows.rs
yellowhatter Feb 13, 2025
c5bca7c
Update windows.rs
yellowhatter Feb 13, 2025
ca26ceb
Update windows.rs
yellowhatter Feb 13, 2025
eee79d7
Update lib.rs, unix.rs, and windows.rs
yellowhatter Feb 13, 2025
3afc716
Update windows.rs
yellowhatter Feb 13, 2025
3f55845
Update windows.rs
yellowhatter Feb 13, 2025
8e2f224
Update windows.rs
yellowhatter Feb 13, 2025
57e628e
Update windows.rs
yellowhatter Feb 13, 2025
8ad701b
Update windows.rs
yellowhatter Feb 13, 2025
247c246
Update windows.rs
yellowhatter Feb 13, 2025
d07248e
Update windows.rs
yellowhatter Feb 14, 2025
f4b5fa7
Update windows.rs
yellowhatter Feb 14, 2025
076fcb3
Update rust.yml and windows.rs
yellowhatter Feb 14, 2025
0bb51cb
Update rust.yml
yellowhatter Feb 14, 2025
7223179
Update rust.yml
yellowhatter Feb 14, 2025
4d72417
Update rust.yml
yellowhatter Feb 14, 2025
f2f2d91
Update rust.yml
yellowhatter Feb 14, 2025
26d4b64
- add public Ext conf access
yellowhatter Feb 14, 2025
2cb18d8
Update windows.rs
yellowhatter Feb 14, 2025
05fc0e6
Update windows.rs
yellowhatter Feb 14, 2025
6d8f6fa
Update windows.rs
yellowhatter Feb 14, 2025
7cbef68
Update windows.rs
yellowhatter Feb 14, 2025
4bf42d2
Update windows.rs
yellowhatter Feb 14, 2025
32c2ab0
Update windows.rs
yellowhatter Feb 14, 2025
39b2618
Update windows.rs
yellowhatter Feb 14, 2025
35d4b61
Update windows.rs
yellowhatter Feb 14, 2025
b870733
Update windows.rs and posix_semantics.rs
yellowhatter Feb 14, 2025
3acb763
Update windows.rs and posix_semantics.rs
yellowhatter Feb 14, 2025
141adbb
Update windows.rs
yellowhatter Feb 14, 2025
9d3ceff
Update rust.yml, windows.rs, and 2 more files...
yellowhatter Feb 14, 2025
9a44e58
Update posix_semantics.rs
yellowhatter Feb 14, 2025
3312e9e
Update rust.yml and posix_semantics.rs
yellowhatter Feb 14, 2025
d45fb93
Update rust.yml
yellowhatter Feb 14, 2025
d74976e
refactor to respect both persistent and non-persistent modes on win
yellowhatter Feb 17, 2025
2ca5c03
Update windows.rs
yellowhatter Feb 17, 2025
f41afd8
Update windows.rs
yellowhatter Feb 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ jobs:

- name: Tests
uses: actions-rs/[email protected]
env:
RUST_LOG: "trace"
with:
command: test
args: --all-features -- --nocapture

- name: Examples
uses: actions-rs/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion examples/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fn increment_value(shmem_flink: &str, thread_num: usize) {
let is_init: &mut AtomicU8;

unsafe {
is_init = &mut *(raw_ptr as *mut u8 as *mut AtomicU8);
is_init = &mut *(raw_ptr as *mut AtomicU8);
raw_ptr = raw_ptr.add(8);
};

Expand Down
11 changes: 9 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ cfg_if! {
compile_error!("shared_memory isnt implemented for this platform...");
}
}
pub use os_impl::ShmemConfExt;

#[derive(Clone, Default)]
/// Struct used to configure different parameters before creating a shared memory mapping
Expand Down Expand Up @@ -100,6 +101,12 @@ impl ShmemConf {
self
}

/// Sets the platform-specific parameters
pub fn ext(mut self, ext: os_impl::ShmemConfExt) -> Self {
self.ext = ext;
self
}

/// Create a new mapping using the current configuration
pub fn create(mut self) -> Result<Shmem, ShmemError> {
if self.size == 0 {
Expand All @@ -118,7 +125,7 @@ impl ShmemConf {
// Generate random ID until one works
loop {
let cur_id = format!("/shmem_{:X}", rand::random::<u64>());
match os_impl::create_mapping(&cur_id, self.size) {
match os_impl::create_mapping(&cur_id, self.size, &self.ext) {
Err(ShmemError::MappingIdExists) => continue,
Ok(m) => break m,
Err(e) => {
Expand All @@ -127,7 +134,7 @@ impl ShmemConf {
};
}
}
Some(ref specific_id) => os_impl::create_mapping(specific_id, self.size)?,
Some(ref specific_id) => os_impl::create_mapping(specific_id, self.size, &self.ext)?,
};
debug!("Created shared memory mapping '{}'", mapping.unique_id);

Expand Down
6 changes: 5 additions & 1 deletion src/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,11 @@ impl MapData {
}

/// Creates a mapping specified by the uid and size
pub fn create_mapping(unique_id: &str, map_size: usize) -> Result<MapData, ShmemError> {
pub fn create_mapping(
unique_id: &str,
map_size: usize,
_: &ShmemConfExt,
) -> Result<MapData, ShmemError> {
//Create shared memory file descriptor
debug!("Creating persistent mapping at {}", unique_id);

Expand Down
173 changes: 99 additions & 74 deletions src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use crate::ShmemError;

#[derive(Clone, Default)]
pub struct ShmemConfExt {
allow_raw: bool,
pub allow_raw: bool,
pub suppress_persistency: bool,
}

impl ShmemConf {
Expand All @@ -19,6 +20,12 @@ impl ShmemConf {
self.ext.allow_raw = allow;
self
}

/// If set to true, the persistency of the object will be suppressed
pub fn suppress_persistency(mut self, suppress: bool) -> Self {
self.ext.suppress_persistency = suppress;
self
}
}

pub struct MapData {
Expand Down Expand Up @@ -73,7 +80,7 @@ impl Drop for MapData {
{
Ok(_) => {
// 2. Rename file to prevent further use
base_path.push(&format!(
base_path.push(format!(
"{}_deleted",
self.unique_id.trim_start_matches('/')
));
Expand Down Expand Up @@ -131,87 +138,62 @@ fn get_tmp_dir() -> Result<PathBuf, ShmemError> {
}
}

fn new_map(
fn map_error<const CREATE: bool>(error: u32) -> Result<MapData, ShmemError> {
Err(if CREATE {
ShmemError::MapCreateFailed(error)
} else {
ShmemError::MapOpenFailed(error)
})
}

fn attach_file_mapping<const CREATE: bool>(
unique_id: &str,
mut map_size: usize,
create: bool,
allow_raw: bool,
map_size: usize,
persistent_file: Option<File>,
) -> Result<MapData, ShmemError> {
// Create file to back the shared memory
let mut file_path = get_tmp_dir()?;
file_path.push(unique_id.trim_start_matches('/'));
debug!(
"{} persistent_file at {}",
if create { "Creating" } else { "Openning" },
file_path.to_string_lossy()
);

let mut opt = OpenOptions::new();
opt.read(true)
.write(true)
.share_mode((FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE).0)
.attributes((FILE_ATTRIBUTE_TEMPORARY).0);
if create {
opt.create_new(true);
} else {
opt.create(false);
};
let map_h = {
debug!(
"{} memory mapping",
if CREATE { "Creating" } else { "Opening" },
);

let mut persistent_file = None;
let map_h = match opt.open(&file_path) {
Ok(f) => {
//Create/open Mapping using persistent file
debug!(
"{} memory mapping",
if create { "Creating" } else { "Openning" },
);
// if there is an existing persistency file OR we create a new mapping, then use CreateFileMapping
if persistent_file.is_some() || CREATE {
let h_handle = persistent_file
.as_ref()
.map(|f| HANDLE(f.as_raw_handle() as _))
.unwrap_or(INVALID_HANDLE_VALUE);
let high_size: u32 = ((map_size as u64 & 0xFFFF_FFFF_0000_0000_u64) >> 32) as u32;
let low_size: u32 = (map_size as u64 & 0xFFFF_FFFF_u64) as u32;
trace!(
"CreateFileMapping({:?}, NULL, {:X}, {}, {}, '{}')",
HANDLE(f.as_raw_handle() as _),
h_handle,
PAGE_READWRITE.0,
high_size,
low_size,
unique_id,
);

match CreateFileMapping(
HANDLE(f.as_raw_handle() as _),
h_handle,
None,
PAGE_READWRITE,
high_size,
low_size,
unique_id,
) {
Ok(v) => {
persistent_file = Some(f);
v
}
Ok(v) => v,
Err(e) => {
let err_code = e.win32_error().unwrap();
return if err_code == ERROR_ALREADY_EXISTS {
Err(ShmemError::MappingIdExists)
} else {
Err(if create {
ShmemError::MapCreateFailed(err_code.0)
} else {
ShmemError::MapOpenFailed(err_code.0)
})
map_error::<CREATE>(err_code.0)
};
}
}
}
Err(e) if e.kind() == ErrorKind::AlreadyExists => return Err(ShmemError::MappingIdExists),
Err(e) => {
if create {
return Err(ShmemError::MapCreateFailed(e.raw_os_error().unwrap() as _));
} else if !allow_raw {
return Err(ShmemError::MapOpenFailed(ERROR_FILE_NOT_FOUND.0));
}

// This may be a mapping that isnt managed by this crate
// Try to open the mapping without any backing file
} else {
// open existing mapping instead
trace!(
"OpenFileMappingW({:?}, {}, '{}')",
FILE_MAP_ALL_ACCESS,
Expand All @@ -237,38 +219,81 @@ fn new_map(
);
let map_ptr = match MapViewOfFile(map_h.as_handle(), FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0) {
Ok(v) => v,
Err(e) => {
return Err(if create {
ShmemError::MapCreateFailed(e.win32_error().unwrap().0)
} else {
ShmemError::MapOpenFailed(e.win32_error().unwrap().0)
})
}
Err(e) => return Err(ShmemError::UnknownOsError(e.win32_error().unwrap().0)),
};
trace!("\t{:p}", map_ptr);

if !create {
//Get the real size of the openned mapping
let mut info = MEMORY_BASIC_INFORMATION::default();
if let Err(e) = VirtualQuery(map_ptr.as_mut_ptr(), &mut info) {
return Err(ShmemError::UnknownOsError(e.win32_error().unwrap().0));
}
map_size = info.RegionSize;
//Get the real size of the opened mapping
let mut info = MEMORY_BASIC_INFORMATION::default();
if let Err(e) = VirtualQuery(map_ptr.as_mut_ptr(), &mut info) {
return Err(ShmemError::UnknownOsError(e.win32_error().unwrap().0));
}

Ok(MapData {
owner: create,
owner: CREATE,
file_map: map_h,
persistent_file,
unique_id: unique_id.to_string(),
map_size,
map_size: info.RegionSize,
view: map_ptr,
})
}

fn attach_persistent_file_mapping<const CREATE: bool>(
unique_id: &str,
map_size: usize,
allow_raw: bool,
) -> Result<MapData, ShmemError> {
// Create file to back the shared memory
let mut file_path = get_tmp_dir()?;
file_path.push(unique_id.trim_start_matches('/'));
debug!(
"{} persistent_file at {}",
if CREATE { "Creating" } else { "Opening" },
file_path.to_string_lossy()
);

match OpenOptions::new()
.read(true)
.write(true)
.share_mode((FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE).0)
.attributes((FILE_ATTRIBUTE_TEMPORARY).0)
.create_new(CREATE)
.create(false)
.open(&file_path)
{
Ok(f) => attach_file_mapping::<CREATE>(unique_id, map_size, Some(f)),
Err(e) if e.kind() == ErrorKind::AlreadyExists => Err(ShmemError::MappingIdExists),
Err(e) => {
if !CREATE && allow_raw {
// This may be a mapping that isnt managed by this crate
// Try to open the mapping without any backing file
return attach_file_mapping::<false>(unique_id, map_size, None);
}
map_error::<CREATE>(e.raw_os_error().unwrap() as _)
}
}
}

//Creates a mapping specified by the uid and size
pub fn attach<const CREATE: bool>(
unique_id: &str,
map_size: usize,
ext: &ShmemConfExt,
) -> Result<MapData, ShmemError> {
match ext.suppress_persistency {
true => attach_file_mapping::<CREATE>(unique_id, map_size, None),
false => attach_persistent_file_mapping::<CREATE>(unique_id, map_size, ext.allow_raw),
}
}

//Creates a mapping specified by the uid and size
pub fn create_mapping(unique_id: &str, map_size: usize) -> Result<MapData, ShmemError> {
new_map(unique_id, map_size, true, false)
pub fn create_mapping(
unique_id: &str,
map_size: usize,
ext: &ShmemConfExt,
) -> Result<MapData, ShmemError> {
attach::<true>(unique_id, map_size, ext)
}

//Opens an existing mapping specified by its uid
Expand All @@ -277,5 +302,5 @@ pub fn open_mapping(
map_size: usize,
ext: &ShmemConfExt,
) -> Result<MapData, ShmemError> {
new_map(unique_id, map_size, false, ext.allow_raw)
attach::<false>(unique_id, map_size, ext)
}
2 changes: 1 addition & 1 deletion tests/general.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fn open_os_id() {
// Drop the owner of the mapping
drop(s1);

// Make sure it can be openned again
// Make sure it can't be openned again
assert!(ShmemConf::new().os_id(&os_id).open().is_err());

drop(s2);
Expand Down
1 change: 1 addition & 0 deletions tests/posix_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ fn persistence() {
shmem.set_owner(false);
String::from(shmem.get_os_id())
};

let mut shmem = ShmemConf::new().os_id(os_id).open().unwrap();
shmem.set_owner(true);
}
Expand Down
21 changes: 21 additions & 0 deletions tests/windows.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#[cfg(target_os = "windows")]
mod windows_tests {
use shared_memory::{ShmemConf, ShmemConfExt};

#[test]
fn suppress_persistency() {
let os_id = {
let mut shmem = ShmemConf::new()
.size(4096)
.ext(ShmemConfExt {
allow_raw: false,
suppress_persistency: true,
})
.create()
.unwrap();
shmem.set_owner(false);
String::from(shmem.get_os_id())
};
assert!(ShmemConf::new().os_id(os_id).open().is_err());
}
}