Skip to content

Commit 969b7e4

Browse files
committed
Some refinement
Signed-off-by: Narfinger <[email protected]>
1 parent 1e7b726 commit 969b7e4

File tree

5 files changed

+71
-10
lines changed

5 files changed

+71
-10
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ fnv = "1.0.3"
4141
futures-channel = { version = "0.3.31", optional = true }
4242
futures-core = { version = "0.3.31", optional = true }
4343
libc = "0.2.162"
44-
serde_core = "1.0"
44+
serde = { version = "1.0", features = ["derive"] }
4545
uuid = { version = "1", features = ["v4"] }
4646

4747
[target.'cfg(any(target_os = "linux", target_os = "openbsd", target_os = "freebsd", target_os = "illumos"))'.dependencies]

src/ipc.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use crate::platform::{
1616
};
1717

1818
use bincode;
19-
use serde_core::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
19+
use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
2020
use std::cell::RefCell;
2121
use std::cmp::min;
2222
use std::error::Error as StdError;
@@ -643,7 +643,7 @@ impl IpcSharedMemory {
643643
}
644644

645645
/// An index to access `IpcSharedMemoryVec`
646-
#[derive(Clone, Debug)]
646+
#[derive(Clone, Debug, Serialize, Deserialize)]
647647
pub struct IpcSharedMemoryIndex(OsIpcSharedMemoryIndex);
648648

649649
/// Shared memory vector that will can be made accessible to a receiver via the reader method
@@ -664,6 +664,18 @@ pub struct IpcSharedMemoryVec {
664664
os_shared_memory_vec: OsIpcSharedMemoryVec,
665665
}
666666

667+
unsafe impl Send for IpcSharedMemoryVec {}
668+
unsafe impl Sync for IpcSharedMemoryVec {}
669+
670+
impl Default for IpcSharedMemoryVec {
671+
fn default() -> Self {
672+
let (memory, _index) = OsIpcSharedMemoryVec::from_bytes(&[0xab]);
673+
IpcSharedMemoryVec {
674+
os_shared_memory_vec: memory,
675+
}
676+
}
677+
}
678+
667679
impl IpcSharedMemoryVec {
668680
pub fn from_bytes(bytes: &[u8]) -> (IpcSharedMemoryVec, IpcSharedMemoryIndex) {
669681
let (memory, index) = OsIpcSharedMemoryVec::from_bytes(bytes);

src/platform/unix/mod.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@ use crate::ipc::{self, IpcMessage};
1111
use bincode;
1212
use fnv::FnvHasher;
1313
use 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
};
1717
use libc::{c_char, c_int, c_void, getsockopt, SO_LINGER, S_IFMT, S_IFSOCK};
1818
use libc::{iovec, msghdr, off_t, recvmsg, sendmsg};
1919
use libc::{sa_family_t, setsockopt, size_t, sockaddr, sockaddr_un, socketpair, socklen_t};
2020
use libc::{EAGAIN, EWOULDBLOCK};
2121
use mio::unix::SourceFd;
2222
use mio::{Events, Interest, Poll, Token};
23+
use serde::{Deserialize, Serialize};
2324
use std::cell::Cell;
2425
use std::cmp;
2526
use 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

816842
impl Drop for BackingStore {
@@ -822,7 +848,7 @@ impl Drop for BackingStore {
822848
}
823849
}
824850

825-
#[derive(Clone, Debug)]
851+
#[derive(Clone, Debug, Serialize, Deserialize)]
826852
pub 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()),

src/router.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use std::sync::{LazyLock, Mutex};
1818
use std::thread::{self, JoinHandle};
1919

2020
use crossbeam_channel::{self, Receiver, Sender};
21-
use serde_core::{Deserialize, Serialize};
21+
use serde::{Deserialize, Serialize};
2222

2323
use crate::ipc::{
2424
self, IpcMessage, IpcReceiver, IpcReceiverSet, IpcSelectionResult, IpcSender, OpaqueIpcReceiver,

src/test.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,11 +544,15 @@ fn shared_memory_object_equality() {
544544

545545
#[test]
546546
fn shared_memory_vec() {
547-
let (vec, index) = IpcSharedMemoryVec::from_bytes(&[0xba; 24]);
547+
let (mut vec, index) = IpcSharedMemoryVec::from_bytes(&[0xba; 24]);
548548
let (tx, rx) = ipc::channel().unwrap();
549549
tx.send(vec.reader()).unwrap();
550550
let received = rx.recv().unwrap();
551551
assert_eq!(vec.get(&index), received.get(&index));
552+
553+
let index2 = vec.push(&[0xbc; 24]);
554+
assert_eq!(vec.get(&index2), received.get(&index2));
555+
assert_eq!(vec.get(&index), received.get(&index));
552556
}
553557

554558
#[test]

0 commit comments

Comments
 (0)