@@ -11,15 +11,16 @@ use crate::ipc::{self, IpcMessage};
1111use bincode;
1212use fnv:: FnvHasher ;
1313use libc:: {
14- self , cmsghdr, linger, CMSG_DATA , CMSG_LEN , CMSG_SPACE , MAP_FAILED , MAP_SHARED , PROT_READ ,
15- PROT_WRITE , SOCK_SEQPACKET , SOL_SOCKET ,
14+ self , cmsghdr, linger, CMSG_DATA , CMSG_LEN , CMSG_SPACE , MAP_FAILED , MAP_FIXED , MAP_NORESERVE ,
15+ MAP_SHARED , PROT_READ , PROT_WRITE , SOCK_SEQPACKET , SOL_SOCKET ,
1616} ;
1717use libc:: { c_char, c_int, c_void, getsockopt, SO_LINGER , S_IFMT , S_IFSOCK } ;
1818use libc:: { iovec, msghdr, off_t, recvmsg, sendmsg} ;
1919use libc:: { sa_family_t, setsockopt, size_t, sockaddr, sockaddr_un, socketpair, socklen_t} ;
2020use libc:: { EAGAIN , EWOULDBLOCK } ;
2121use mio:: unix:: SourceFd ;
2222use mio:: { Events , Interest , Poll , Token } ;
23+ use serde:: { Deserialize , Serialize } ;
2324use std:: cell:: Cell ;
2425use std:: cmp;
2526use std:: collections:: HashMap ;
@@ -811,6 +812,31 @@ impl BackingStore {
811812 assert ! ( address != MAP_FAILED ) ;
812813 ( address as * mut u8 , length)
813814 }
815+
816+ pub unsafe fn map_file_noreserve ( & self , length : Option < size_t > ) -> ( * mut u8 , size_t ) {
817+ let length = length. unwrap_or_else ( || {
818+ let mut st = mem:: MaybeUninit :: uninit ( ) ;
819+ if libc:: fstat ( self . fd , st. as_mut_ptr ( ) ) != 0 {
820+ panic ! ( "error stating fd {}: {}" , self . fd, UnixError :: last( ) ) ;
821+ }
822+ st. assume_init ( ) . st_size as size_t
823+ } ) ;
824+ if length == 0 {
825+ // This will cause `mmap` to fail, so handle it explicitly.
826+ return ( ptr:: null_mut ( ) , length) ;
827+ }
828+ let address = libc:: mmap (
829+ ptr:: null_mut ( ) ,
830+ length,
831+ PROT_READ | PROT_WRITE ,
832+ MAP_SHARED | MAP_NORESERVE ,
833+ self . fd ,
834+ 0 ,
835+ ) ;
836+ assert ! ( !address. is_null( ) ) ;
837+ assert ! ( address != MAP_FAILED ) ;
838+ ( address as * mut u8 , length)
839+ }
814840}
815841
816842impl Drop for BackingStore {
@@ -822,7 +848,7 @@ impl Drop for BackingStore {
822848 }
823849}
824850
825- #[ derive( Clone , Debug ) ]
851+ #[ derive( Clone , Debug , Serialize , Deserialize ) ]
826852pub struct OsIpcSharedMemoryIndex {
827853 // The offset in bytes
828854 offset : usize ,
@@ -840,7 +866,7 @@ impl OsIpcSharedMemoryVec {
840866 pub fn from_bytes ( bytes : & [ u8 ] ) -> ( OsIpcSharedMemoryVec , OsIpcSharedMemoryIndex ) {
841867 unsafe {
842868 let store = BackingStore :: new ( bytes. len ( ) ) ;
843- let ( address, _) = store. map_file ( Some ( bytes . len ( ) ) ) ;
869+ let ( address, _) = store. map_file_noreserve ( Some ( 512_000_000 ) ) ;
844870 ptr:: copy_nonoverlapping ( bytes. as_ptr ( ) , address, bytes. len ( ) ) ;
845871 let memory = OsIpcSharedMemoryVec {
846872 ptr : address,
@@ -866,7 +892,21 @@ impl OsIpcSharedMemoryVec {
866892 pub fn push ( & mut self , bytes : & [ u8 ] ) -> OsIpcSharedMemoryIndex {
867893 let fd = self . store . fd ( ) ;
868894 let index = unsafe {
869- libc:: ftruncate ( fd, ( self . length + bytes. len ( ) ) . try_into ( ) . unwrap ( ) ) ;
895+ assert_eq ! (
896+ 0 ,
897+ libc:: ftruncate( fd, ( self . length + bytes. len( ) ) . try_into( ) . unwrap( ) )
898+ ) ;
899+
900+ let new_length = self . length + bytes. len ( ) ;
901+ // map more of the file into the address space
902+ let address = libc:: mmap (
903+ self . ptr . byte_offset ( self . length . try_into ( ) . unwrap ( ) ) as * mut c_void ,
904+ bytes. len ( ) ,
905+ PROT_READ | PROT_WRITE ,
906+ MAP_SHARED | MAP_FIXED ,
907+ self . store . fd ,
908+ 0 ,
909+ ) ;
870910 ptr:: copy_nonoverlapping (
871911 bytes. as_ptr ( ) ,
872912 self . ptr . byte_offset ( self . length as isize ) ,
@@ -882,6 +922,11 @@ impl OsIpcSharedMemoryVec {
882922 }
883923
884924 pub fn get ( & self , index : & OsIpcSharedMemoryIndex ) -> & [ u8 ] {
925+ // While it would be nice to check index vs length here, we cannot.
926+ // The length in this object might be a reader that was sent a long time ago
927+ // The length does not get updated for the object, only for the main IpcSharedMemoryVec
928+ // This is in general fine as we only produce indices for objects that exists _and_ we
929+ // can never delete objects.
885930 unsafe {
886931 slice:: from_raw_parts (
887932 self . ptr . byte_offset ( index. offset . try_into ( ) . unwrap ( ) ) ,
0 commit comments