@@ -53,7 +53,12 @@ mod mmap {
5353 | libc:: MADV_SEQUENTIAL
5454 | libc:: MADV_WILLNEED
5555 | libc:: MADV_DONTNEED => Ok ( advice) ,
56- #[ cfg( any( target_os = "linux" , target_os = "macos" , target_os = "ios" ) ) ]
56+ #[ cfg( any(
57+ target_os = "linux" ,
58+ target_os = "macos" ,
59+ target_os = "ios" ,
60+ target_os = "freebsd"
61+ ) ) ]
5762 libc:: MADV_FREE => Ok ( advice) ,
5863 #[ cfg( target_os = "linux" ) ]
5964 libc:: MADV_DONTFORK
@@ -66,6 +71,12 @@ mod mmap {
6671 | libc:: MADV_DONTDUMP
6772 | libc:: MADV_DODUMP
6873 | libc:: MADV_HWPOISON => Ok ( advice) ,
74+ #[ cfg( target_os = "freebsd" ) ]
75+ libc:: MADV_NOSYNC
76+ | libc:: MADV_AUTOSYNC
77+ | libc:: MADV_NOCORE
78+ | libc:: MADV_CORE
79+ | libc:: MADV_PROTECT => Ok ( advice) ,
6980 _ => Err ( vm. new_value_error ( "Not a valid Advice value" ) ) ,
7081 }
7182 }
@@ -96,7 +107,7 @@ mod mmap {
96107 #[ pyattr]
97108 use libc:: {
98109 MADV_DONTNEED , MADV_NORMAL , MADV_RANDOM , MADV_SEQUENTIAL , MADV_WILLNEED , MAP_ANON ,
99- MAP_ANONYMOUS , MAP_PRIVATE , MAP_SHARED , PROT_READ , PROT_WRITE ,
110+ MAP_ANONYMOUS , MAP_PRIVATE , MAP_SHARED , PROT_EXEC , PROT_READ , PROT_WRITE ,
100111 } ;
101112
102113 #[ cfg( target_os = "macos" ) ]
@@ -146,6 +157,16 @@ mod mmap {
146157 #[ pyattr]
147158 use libc:: { MAP_DENYWRITE , MAP_EXECUTABLE , MAP_POPULATE } ;
148159
160+ // MAP_STACK is available on Linux, OpenBSD, and NetBSD
161+ #[ cfg( any( target_os = "linux" , target_os = "openbsd" , target_os = "netbsd" ) ) ]
162+ #[ pyattr]
163+ use libc:: MAP_STACK ;
164+
165+ // FreeBSD-specific MADV constants
166+ #[ cfg( target_os = "freebsd" ) ]
167+ #[ pyattr]
168+ use libc:: { MADV_AUTOSYNC , MADV_CORE , MADV_NOCORE , MADV_NOSYNC , MADV_PROTECT } ;
169+
149170 #[ pyattr]
150171 const ACCESS_DEFAULT : u32 = AccessMode :: Default as u32 ;
151172 #[ pyattr]
@@ -404,6 +425,15 @@ mod mmap {
404425 } ;
405426
406427 let fd = unsafe { crt_fd:: Borrowed :: try_borrow_raw ( fd) } ;
428+
429+ // macOS: Issue #11277: fsync(2) is not enough on OS X - a special, OS X specific
430+ // fcntl(2) is necessary to force DISKSYNC and get around mmap(2) bug
431+ #[ cfg( target_os = "macos" ) ]
432+ if let Ok ( fd) = fd {
433+ use std:: os:: fd:: AsRawFd ;
434+ unsafe { libc:: fcntl ( fd. as_raw_fd ( ) , libc:: F_FULLFSYNC ) } ;
435+ }
436+
407437 if let Ok ( fd) = fd {
408438 let metadata = fstat ( fd)
409439 . map_err ( |err| io:: Error :: from_raw_os_error ( err as i32 ) . to_pyexception ( vm) ) ?;
@@ -799,8 +829,9 @@ mod mmap {
799829
800830 let sub = & options. sub ;
801831
832+ // returns start position for empty string
802833 if sub. is_empty ( ) {
803- return Ok ( PyInt :: from ( 0isize ) ) ;
834+ return Ok ( PyInt :: from ( start as isize ) ) ;
804835 }
805836
806837 let mmap = self . check_valid ( vm) ?;
@@ -815,8 +846,9 @@ mod mmap {
815846 let ( start, end) = self . get_find_range ( options. clone ( ) ) ;
816847
817848 let sub = & options. sub ;
849+ // returns start position for empty string
818850 if sub. is_empty ( ) {
819- return Ok ( PyInt :: from ( 0isize ) ) ;
851+ return Ok ( PyInt :: from ( start as isize ) ) ;
820852 }
821853
822854 let mmap = self . check_valid ( vm) ?;
@@ -850,18 +882,20 @@ mod mmap {
850882 #[ cfg( all( unix, not( target_os = "redox" ) ) ) ]
851883 #[ pymethod]
852884 fn madvise ( & self , options : AdviseOptions , vm : & VirtualMachine ) -> PyResult < ( ) > {
853- let ( option, _start , _length ) = options. values ( self . __len__ ( ) , vm) ?;
885+ let ( option, start , length ) = options. values ( self . __len__ ( ) , vm) ?;
854886 let advice = validate_advice ( vm, option) ?;
855887
856888 let guard = self . check_valid ( vm) ?;
857889 let mmap = guard. deref ( ) . as_ref ( ) . unwrap ( ) ;
858- let ( ptr, len ) = match mmap {
859- MmapObj :: Read ( m) => ( m. as_ptr ( ) , m . len ( ) ) ,
860- MmapObj :: Write ( m) => ( m. as_ptr ( ) , m . len ( ) ) ,
890+ let ptr = match mmap {
891+ MmapObj :: Read ( m) => m. as_ptr ( ) ,
892+ MmapObj :: Write ( m) => m. as_ptr ( ) ,
861893 } ;
862894
863- // Call libc::madvise directly
864- let result = unsafe { libc:: madvise ( ptr as * mut libc:: c_void , len, advice) } ;
895+ // Apply madvise to the specified range (start, length)
896+ let ptr_with_offset = unsafe { ptr. add ( start) } ;
897+ let result =
898+ unsafe { libc:: madvise ( ptr_with_offset as * mut libc:: c_void , length, advice) } ;
865899 if result != 0 {
866900 return Err ( io:: Error :: last_os_error ( ) . to_pyexception ( vm) ) ;
867901 }
@@ -1063,13 +1097,14 @@ mod mmap {
10631097 // Restore original mmap on error
10641098 let err = io:: Error :: last_os_error ( ) ;
10651099 let old_size = self . size . load ( ) ;
1066- if let Ok ( mmap ) = Self :: create_mmap_windows (
1100+ match Self :: create_mmap_windows (
10671101 handle as HANDLE ,
10681102 self . offset ,
10691103 old_size,
10701104 & self . access ,
10711105 ) {
1072- * mmap_guard = Some ( mmap) ;
1106+ Ok ( mmap) => * mmap_guard = Some ( mmap) ,
1107+ Err ( _) => self . closed . store ( true ) ,
10731108 }
10741109 return Err ( err. to_pyexception ( vm) ) ;
10751110 }
@@ -1078,13 +1113,14 @@ mod mmap {
10781113 if result == 0 {
10791114 let err = io:: Error :: last_os_error ( ) ;
10801115 let old_size = self . size . load ( ) ;
1081- if let Ok ( mmap ) = Self :: create_mmap_windows (
1116+ match Self :: create_mmap_windows (
10821117 handle as HANDLE ,
10831118 self . offset ,
10841119 old_size,
10851120 & self . access ,
10861121 ) {
1087- * mmap_guard = Some ( mmap) ;
1122+ Ok ( mmap) => * mmap_guard = Some ( mmap) ,
1123+ Err ( _) => self . closed . store ( true ) ,
10881124 }
10891125 return Err ( err. to_pyexception ( vm) ) ;
10901126 }
@@ -1248,6 +1284,12 @@ mod mmap {
12481284 fn __exit__ ( zelf : & Py < Self > , _args : FuncArgs , vm : & VirtualMachine ) -> PyResult < ( ) > {
12491285 zelf. close ( vm)
12501286 }
1287+
1288+ #[ cfg( windows) ]
1289+ #[ pymethod]
1290+ fn __sizeof__ ( & self ) -> usize {
1291+ std:: mem:: size_of :: < Self > ( )
1292+ }
12511293 }
12521294
12531295 impl PyMmap {
0 commit comments