@@ -2,49 +2,39 @@ use std::fs::{File, OpenOptions};
22use std:: io:: ErrorKind ;
33use std:: os:: windows:: { fs:: OpenOptionsExt , io:: AsRawHandle } ;
44use std:: path:: PathBuf ;
5- use std:: ptr:: null_mut;
65
76use crate :: log:: * ;
87use win_sys:: * ;
9- use win_sys:: Foundation :: INVALID_HANDLE_VALUE ;
108
119use crate :: ShmemError ;
1210
1311pub struct MapData {
1412 owner : bool ,
1513
16- ///The handle to our open mapping
17- map_handle : HANDLE ,
14+ /// Pointer to the first byte of our mapping
15+ /// Keep this above `file_map` so it gets dropped first
16+ pub view : ViewOfFile ,
17+
18+ /// The handle to our open mapping
19+ #[ allow( dead_code) ]
20+ file_map : FileMapping ,
1821
1922 /// This file is used for shmem persistence. When an owner wants to drop the mapping,
2023 /// it opens the file with FILE_FLAG_DELETE_ON_CLOSE, renames the file and closes it.
2124 /// This makes it so future calls to open the old mapping will fail (as it was renamed) and
2225 /// deletes the renamed file once all handles have been closed.
26+ #[ allow( dead_code) ]
2327 persistent_file : Option < File > ,
2428
2529 //Shared mapping uid
2630 pub unique_id : String ,
2731 //Total size of the mapping
2832 pub map_size : usize ,
29- //Pointer to the first byte of our mapping
30- pub map_ptr : * mut u8 ,
3133}
3234///Teardown UnmapViewOfFile and close CreateMapping handle
3335impl Drop for MapData {
3436 ///Takes care of properly closing the SharedMem
3537 fn drop ( & mut self ) {
36- //Unmap memory from our process
37- if !self . map_ptr . is_null ( ) {
38- trace ! ( "UnmapViewOfFile(map_ptr:{:p})" , self . map_ptr) ;
39- let _ = UnmapViewOfFile ( self . map_ptr as _ ) ;
40- }
41-
42- //Close our mapping
43- if self . map_handle . 0 != 0 {
44- trace ! ( "CloseHandle(map_handle:0x{:X})" , self . map_handle. 0 ) ;
45- let _ = CloseHandle ( self . map_handle ) ;
46- }
47-
4838 // Inspired by the boost implementation at
4939 // https://github.com/boostorg/interprocess/blob/140b50efb3281fa3898f3a4cf939cfbda174718f/include/boost/interprocess/detail/win32_api.hpp
5040 // Emulate POSIX behavior by
@@ -105,6 +95,9 @@ impl MapData {
10595 self . owner = is_owner;
10696 prev_val
10797 }
98+ pub fn as_mut_ptr ( & self ) -> * mut u8 {
99+ self . view . as_mut_ptr ( ) as _
100+ }
108101}
109102
110103/// Returns the path to a temporary directory in which to store files backing the shared memory. If it
@@ -125,20 +118,13 @@ fn get_tmp_dir() -> Result<PathBuf, ShmemError> {
125118 }
126119}
127120
128- fn new_map ( unique_id : & str , map_size : usize , create : bool ) -> Result < MapData , ShmemError > {
129- let mut f = None ;
130- let mut map_h = HANDLE ( 0 ) ;
131-
121+ fn new_map ( unique_id : & str , map_size : usize , create : bool ) -> Result < MapData , ShmemError > {
132122 // Create file to back the shared memory
133123 let mut file_path = get_tmp_dir ( ) ?;
134124 file_path. push ( unique_id. trim_start_matches ( '/' ) ) ;
135125 debug ! (
136126 "{} persistent_file at {}" ,
137- if create {
138- "Creating"
139- } else {
140- "Openning"
141- } ,
127+ if create { "Creating" } else { "Openning" } ,
142128 file_path. to_string_lossy( )
143129 ) ;
144130
@@ -153,120 +139,108 @@ fn new_map(unique_id: &str, map_size: usize, create: bool) -> Result<MapData, S
153139 opt. create ( false ) ;
154140 } ;
155141
156- f = match opt. open ( & file_path)
157- {
158- Ok ( f) => Some ( f) ,
159- Err ( e) if e. kind ( ) == ErrorKind :: AlreadyExists => return Err ( ShmemError :: MappingIdExists ) ,
160- Err ( e) => return Err (
161- if create {
162- ShmemError :: MapCreateFailed ( e. raw_os_error ( ) . unwrap ( ) as _ )
163- } else {
164- debug ! ( "Failed to open persistent posix mapping... Try to open raw shared memory by ID" ) ;
165- // Allow openning memory mappings not managed by this crate
166- // which do not create a file on disk for the mapping
167- ShmemError :: MapOpenFailed ( e. raw_os_error ( ) . unwrap ( ) as _ )
168- } ) ,
169- } ;
142+ let mut persistent_file = None ;
143+ let map_h = match opt. open ( & file_path) {
144+ Ok ( f) => {
145+ //Create/open Mapping using persistent file
146+ debug ! (
147+ "{} memory mapping" ,
148+ if create { "Creating" } else { "Openning" } ,
149+ ) ;
150+ let high_size: u32 = ( ( map_size as u64 & 0xFFFF_FFFF_0000_0000_u64 ) >> 32 ) as u32 ;
151+ let low_size: u32 = ( map_size as u64 & 0xFFFF_FFFF_u64 ) as u32 ;
152+ trace ! (
153+ "CreateFileMapping({:?}, NULL, {:X}, {}, {}, '{}')" ,
154+ HANDLE ( f. as_raw_handle( ) as _) ,
155+ PAGE_READWRITE . 0 ,
156+ high_size,
157+ low_size,
158+ unique_id,
159+ ) ;
170160
171- // Start using MapData ASAP to rely on auto cleanup through Drop
172- let mut new_map: MapData = MapData {
173- owner : create,
174- persistent_file : f,
175- unique_id : String :: from ( unique_id) ,
176- map_handle : map_h,
177- map_size,
178- map_ptr : null_mut ( ) ,
179- } ;
180-
181- if new_map. map_handle . 0 == 0 {
182- //Create Mapping
183- debug ! ( "{} memory mapping" ,
161+ match CreateFileMapping (
162+ HANDLE ( f. as_raw_handle ( ) as _ ) ,
163+ None ,
164+ PAGE_READWRITE ,
165+ high_size,
166+ low_size,
167+ unique_id,
168+ ) {
169+ Ok ( v) => {
170+ persistent_file = Some ( f) ;
171+ v
172+ }
173+ Err ( e) => {
174+ let err_code = e. win32_error ( ) . unwrap ( ) ;
175+ return if err_code == ERROR_ALREADY_EXISTS {
176+ Err ( ShmemError :: MappingIdExists )
177+ } else {
178+ Err ( if create {
179+ ShmemError :: MapCreateFailed ( err_code. 0 )
180+ } else {
181+ ShmemError :: MapOpenFailed ( err_code. 0 )
182+ } )
183+ } ;
184+ }
185+ }
186+ }
187+ Err ( e) if e. kind ( ) == ErrorKind :: AlreadyExists => return Err ( ShmemError :: MappingIdExists ) ,
188+ Err ( e) => {
184189 if create {
185- "Creating"
186- } else {
187- "Openning"
188- } ,
189- ) ;
190- let high_size: u32 = ( ( map_size as u64 & 0xFFFF_FFFF_0000_0000_u64 ) >> 32 ) as u32 ;
191- let low_size: u32 = ( map_size as u64 & 0xFFFF_FFFF_u64 ) as u32 ;
192- trace ! (
193- "CreateFileMappingW({:?}, NULL, {:X}, {}, {}, '{}') == 0x{:X}" ,
194- new_map. persistent_file,
195- PAGE_READWRITE . 0 ,
196- high_size,
197- low_size,
198- new_map. unique_id,
199- new_map. map_handle. 0
200- ) ;
190+ return Err ( ShmemError :: MapCreateFailed ( e. raw_os_error ( ) . unwrap ( ) as _ ) ) ;
191+ }
201192
202- new_map. map_handle = match CreateFileMappingW (
203- if let Some ( h) = & new_map. persistent_file {
204- HANDLE ( h. as_raw_handle ( ) as _ )
205- } else {
206- INVALID_HANDLE_VALUE
207- } ,
208- None ,
209- PAGE_READWRITE ,
210- high_size,
211- low_size,
212- unique_id,
213- ) {
214- Ok ( v) => v,
215- Err ( e) => {
216- let err_code = e. win32_error ( ) . unwrap ( ) ;
217- return if err_code == ERROR_ALREADY_EXISTS . 0 {
218- Err ( ShmemError :: MappingIdExists )
219- } else {
220- Err ( if create {
221- ShmemError :: MapCreateFailed ( err_code)
222- } else {
223- ShmemError :: MapOpenFailed ( err_code)
224- } )
225- } ;
193+ // This may be a mapping that isnt managed by this crate
194+ // Try to open the mapping without any backing file
195+ trace ! (
196+ "OpenFileMappingW({:?}, {}, '{}')" ,
197+ FILE_MAP_ALL_ACCESS ,
198+ false ,
199+ unique_id,
200+ ) ;
201+ match OpenFileMapping ( FILE_MAP_ALL_ACCESS , false , unique_id) {
202+ Ok ( h) => h,
203+ Err ( e) => {
204+ return Err ( ShmemError :: MapOpenFailed ( e. win32_error ( ) . unwrap ( ) . 0 ) ) ;
205+ }
226206 }
227- } ;
207+ }
208+ } ;
209+ trace ! ( "0x{:X}" , map_h) ;
228210
229- trace ! (
230- "CreateFileMappingW({:?}, NULL, {:X}, {}, {}, '{}') == 0x{:X}" ,
231- new_map. persistent_file,
232- PAGE_READWRITE . 0 ,
233- high_size,
234- low_size,
235- new_map. unique_id,
236- new_map. map_handle. 0
237- ) ;
238- }
239-
240211 //Map mapping into address space
241212 debug ! ( "Loading mapping into address space" ) ;
242213 trace ! (
243214 "MapViewOfFile(0x{:X}, {:X}, 0, 0, 0)" ,
244- new_map . map_handle . 0 ,
215+ map_h ,
245216 ( FILE_MAP_READ | FILE_MAP_WRITE ) . 0 ,
246217 ) ;
247-
248- new_map. map_ptr =
249- match MapViewOfFile ( new_map. map_handle , FILE_MAP_READ | FILE_MAP_WRITE , 0 , 0 , 0 ) {
250- Ok ( v) => v as _ ,
251- Err ( e) => return Err ( if create {
252- ShmemError :: MapCreateFailed ( e. win32_error ( ) . unwrap ( ) )
218+ let map_ptr = match MapViewOfFile ( map_h. as_handle ( ) , FILE_MAP_READ | FILE_MAP_WRITE , 0 , 0 , 0 ) {
219+ Ok ( v) => v as _ ,
220+ Err ( e) => {
221+ return Err ( if create {
222+ ShmemError :: MapCreateFailed ( e. win32_error ( ) . unwrap ( ) . 0 )
253223 } else {
254- ShmemError :: MapOpenFailed ( e. win32_error ( ) . unwrap ( ) )
255- } ) ,
256- } ;
257-
258- trace ! (
259- "MapViewOfFile(0x{:X}, {:X}, 0, 0, 0) == {:p}" ,
260- new_map. map_handle. 0 ,
261- ( FILE_MAP_READ | FILE_MAP_WRITE ) . 0 ,
262- new_map. map_ptr
263- ) ;
224+ ShmemError :: MapOpenFailed ( e. win32_error ( ) . unwrap ( ) . 0 )
225+ } )
226+ }
227+ } ;
228+ trace ! ( "\t {:p}" , map_ptr) ;
229+
230+ let mut new_map = MapData {
231+ owner : create,
232+ file_map : map_h,
233+ persistent_file,
234+ unique_id : unique_id. to_string ( ) ,
235+ map_size : 0 ,
236+ view : map_ptr,
237+ } ;
264238
265239 if !create {
266240 //Get the real size of the openned mapping
267241 let mut info = MEMORY_BASIC_INFORMATION :: default ( ) ;
268- if let Err ( e) = VirtualQuery ( new_map. map_ptr as _ , & mut info) {
269- return Err ( ShmemError :: UnknownOsError ( e. win32_error ( ) . unwrap ( ) ) ) ;
242+ if let Err ( e) = VirtualQuery ( new_map. view . as_mut_ptr ( ) as _ , & mut info) {
243+ return Err ( ShmemError :: UnknownOsError ( e. win32_error ( ) . unwrap ( ) . 0 ) ) ;
270244 }
271245 new_map. map_size = info. RegionSize ;
272246 }
0 commit comments